# Decodificação assistida

O decodificação assistida acelera a geração de texto ao permitir que um modelo auxiliar proponha tokens candidatos antes que o modelo principal os confirme. O modelo principal verifica os tokens candidatos em uma única passagem de frente. O modelo auxiliar é rápido e barato e pode substituir dezenas de passagens de frente mais caras do modelo principal.

Este guia aborda os métodos de decodificação assistida no Transformers.

## Decodificação especulativa

O [decodificação especulativa](https://hf.co/papers/2211.17192) usa um modelo assistente menor para rascunhar tokens candidatos. O modelo principal verifica esses tokens em uma única passagem. Os tokens validados entram na saída final e os tokens rejeitados disparam a amostragem padrão. A geração é mais rápida porque o modelo principal executa menos passes de frente caros.

O método funciona melhor quando o modelo assistente é significativamente menor que o modelo principal e usa o mesmo tokenizer. O speculative decoding suporta busca gulosa e amostragem, mas não entradas em lote.

Passe `assistant_model` para [generate()](/docs/transformers/main/pt/main_classes/text_generation#transformers.GenerationMixin.generate). Defina `do_sample=True` para reamostrar caso a validação do token falhe.

```py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM-1.7B")
model = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM-1.7B", dtype="auto")
assistant_model = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM-135M", dtype="auto")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt")

outputs = model.generate(**inputs, assistant_model=assistant_model)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
'Hugging Face is an open-source company that provides a platform for developers to build and deploy machine'
```

O argumento `assistant_model` também está disponível na API [Pipeline](/docs/transformers/main/pt/main_classes/pipelines#transformers.Pipeline).

```python
import torch
from transformers import pipeline

pipeline = pipeline(
    "text-generation",
    model="meta-llama/Llama-3.1-8B",
    assistant_model="meta-llama/Llama-3.2-1B",
    dtype="auto"
)
pipeline("Hugging Face is an open-source company, ", max_new_tokens=50, do_sample=False)
```

Defina `temperature` para controlar a aleatoriedade. Temperaturas mais baixas geralmente melhoram a latência.

```py
from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM-1.7B")
model = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM-1.7B", dtype="auto")
assistant_model = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM-135M", dtype="auto")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt")

outputs = model.generate(**inputs, assistant_model=assistant_model, do_sample=True, temperature=0.5)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
'Hugging Face is an open-source company that is dedicated to creating a better world through technology.'
```

## Decodificação por busca de prompt

O prompt lookup decoding não requer um modelo assistente. Ele localiza n-grams sobrepostos no prompt para propor tokens candidatos. Se não houver correspondência, ele recorre ao decodificação autoregressiva normal. Isso se adequa a tarefas baseadas na entrada, como sumarização e tradução, porque os tokens candidatos frequentemente espelham padrões locais no texto de origem.

Passe `prompt_lookup_num_tokens` para [generate()](/docs/transformers/main/pt/main_classes/text_generation#transformers.GenerationMixin.generate). Isso define quantos tokens o algoritmo tenta copiar de uma parte anterior do prompt quando detecta um padrão repetido.

```py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM-1.7B")
model = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM-1.7B", dtype="auto")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt")

outputs = model.generate(**inputs, prompt_lookup_num_tokens=5)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
'Hugging Face is an open-source company that provides a platform for developers to build and deploy machine learning models. It offers a variety of tools'
```

```py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM-1.7B")
model = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM-1.7B", dtype="auto")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt")

outputs = model.generate(**inputs, prompt_lookup_num_tokens=5, do_sample=True, temperature=0.5)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
'Hugging Face is an open-source company that provides a platform for developers to build and deploy machine learning models. It offers a variety of tools'
```

## Decodificação especulativa autônoma

O decodificação especulativa autônoma utiliza as camadas intermediárias de um modelo como assistente para propor tokens candidatos. Se a proposta corresponder, o modelo encerra precocemente e as camadas restantes verificam ou corrigem os tokens.

Como se trata de um único modelo, os pesos e os caches são compartilhados, o que aumenta a velocidade sem sobrecarga adicional de memória. Essa técnica só funciona para modelos treinados para suportar logits de saída antecipada a partir de camadas intermediárias.

Passe `assistant_early_exit` para [generate()](/docs/transformers/main/pt/main_classes/text_generation#transformers.GenerationMixin.generate) para definir a camada de saída.

```py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("facebook/layerskip-llama3.2-1B")
model = AutoModelForCausalLM.from_pretrained("facebook/layerskip-llama3.2-1B", dtype="auto")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt")

outputs = model.generate(**inputs, assistant_early_exit=4, do_sample=False, max_new_tokens=20)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
```

## Camada de previsão de múltiplos tokens (MTP)

A camada de previsão de múltiplos tokens (MTP) rascunha tokens candidatos com camadas de previsão extras que vêm do próprio checkpoint do modelo principal. As camadas MTP reutilizam os embeddings e a cabeça de saída do modelo principal. Cada camada MTP rascunha um token, de modo que o número de candidatos por etapa corresponde à contagem de camadas MTP do checkpoint. O modelo principal verifica os rascunhos em uma única passagem de frente.

O MTP funciona apenas com checkpoints treinados com camadas MTP, como [DeepSeek-V3](https://huggingface.co/deepseek-ai/DeepSeek-V3) e [GLM-4.5](https://huggingface.co/zai-org/GLM-4.5). Esses checkpoints contêm pesos MTP e definem `num_mtp_layers` em sua configuração, listado como `num_nextn_predict_layers` em `config.json`.

Passe `use_mtp=True` para [generate()](/docs/transformers/main/pt/main_classes/text_generation#transformers.GenerationMixin.generate), que gera um erro se o modelo não tiver camadas MTP. Assim como o speculative decoding, o MTP suporta busca gulosa e amostragem, mas não suporta entradas em lote.

Aqui, MTP se refere às camadas de previsão incluídas no checkpoint de destino, como em DeepSeek-V3 e GLM-4.5. O Gemma 4 usa um checkpoint de assistente separado para decodificação MTP. Passe-o como `assistant_model` (veja [Drafter de previsão de múltiplos tokens](#multi-token-prediction-drafter)).

O pipeline `text-generation` e o [generate()](/docs/transformers/main/pt/main_classes/text_generation#transformers.GenerationMixin.generate) aceitam `use_mtp=True`.

```py
from transformers import pipeline

pipe = pipeline(
    "text-generation",
    model="zai-org/GLM-4.5-Air",
    device_map="auto",
)

outputs = pipe(
    "Hugging Face is an open-source company",
    use_mtp=True,
    do_sample=False,
    max_new_tokens=50,
    add_special_tokens=True,
    return_full_text=True,
)

[output["generated_text"] for output in outputs]
```

Alternativamente, você pode inferir da seguinte forma.

```py
from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("zai-org/GLM-4.5-Air")
model = AutoModelForCausalLM.from_pretrained("zai-org/GLM-4.5-Air", device_map="auto")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt").to(model.device)

outputs = model.generate(**inputs, use_mtp=True, do_sample=False, max_new_tokens=50)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
```

## Drafter de previsão de múltiplos tokens

Um redator MTP é um modelo assistente leve carregado a partir de um checkpoint separado. Ele propõe tokens candidatos para que o modelo de destino os verifique. O redator usa os embeddings de entrada do modelo de destino e atende ao cache de KV deste. Ele parte dos estados ocultos do modelo de destino e, em seguida, redige tokens de forma autoregressiva. Para cada próximo token, ele alimenta seu estado oculto projetado de volta ao redator. O modelo de destino verifica os tokens redigidos em uma única passagem de frente, assim como no decodificação especulativa.

Diferentemente das camadas MTP, que fazem parte do checkpoint de destino e compartilham sua cabeça de saída, um redator MTP é um modelo assistente separado. Ele usa os embeddings de entrada e o cache KV do modelo de destino para propor tokens.

```py
from transformers import AutoProcessor, AutoModelForCausalLM

processor = AutoProcessor.from_pretrained("google/gemma-4-E4B-it")
target_model = AutoModelForCausalLM.from_pretrained(
    "google/gemma-4-E4B-it",
    dtype="auto",
    device_map="auto",

)

assistant_model = AutoModelForCausalLM.from_pretrained(
    "google/gemma-4-E4B-it-assistant",
    dtype="auto",
    device_map="auto",
)

messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Write a short joke about saving RAM."},
]

inputs = processor.apply_chat_template(
    messages,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
    add_generation_prompt=True,
    enable_thinking=False
).to(target_model.device)
input_len = inputs["input_ids"].shape[-1]

outputs = target_model.generate(
    **inputs,
    assistant_model=assistant_model,
    max_new_tokens=256,
)
response = processor.decode(outputs[0][input_len:], skip_special_tokens=False)

processor.parse_response(response)
```

## Decodificação assistida universal

O decodificação assistida universal (UAD) torna a decodificação especulativa possível mesmo quando os modelos principal e assistente possuem tokenizers diferentes. Ele permite combinar qualquer modelo assistente pequeno com o modelo principal. Os tokens candidatos são re-codificados e o algoritmo calcula a subsequência comum mais longa para que a continuação permaneça alinhada.

Passe `tokenizer`, `assistant_tokenizer` e `assistant_model` para [generate()](/docs/transformers/main/pt/main_classes/text_generation#transformers.GenerationMixin.generate) para habilitar o UAD.

```py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

assistant_tokenizer = AutoTokenizer.from_pretrained("double7/vicuna-68m")
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-9b")
model = AutoModelForCausalLM.from_pretrained("google/gemma-2-9b", dtype="auto")
assistant_model = AutoModelForCausalLM.from_pretrained("double7/vicuna-68m", dtype="auto")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt")

outputs = model.generate(**inputs, assistant_model=assistant_model, tokenizer=tokenizer, assistant_tokenizer=assistant_tokenizer)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
'Hugging Face is an open-source company that is dedicated to creating a better world through technology.'
```

### Verificação de ensemble estático

O decodificação especulativa padrão é *sem perdas* — ela garante que a distribuição de saída corresponda exatamente à do modelo de destino. A [verificação de ensemble estática](https://arxiv.org/abs/2604.07622) relaxa isso ao verificar contra uma mistura das distribuições de destino e de rascunho, aumentando a taxa de aceitação (inferência mais rápida) ao custo de tornar a distribuição de saída uma mistura, em vez da distribuição de destino exata. Um valor inicial recomendado é `0.7`.

```python
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM-1.7B")
model = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM-1.7B", dtype="auto")
assistant_model = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM-135M", dtype="auto")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt")

outputs = model.generate(**inputs, assistant_model=assistant_model, assistant_ensemble_weight=0.7, do_sample=True)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
```

Isso requer logits candidatas do modelo assistente e não é suportado com prompt lookup decoding.

## Recursos

- Leia o post no blog [Assisted Generation: a new direction toward low-latency text generation](https://huggingface.co/blog/assisted-generation) para mais contexto sobre a latência de geração de texto e a geração assistida.

