Constrained Decoding
A decodificação restrita mascara tokens inválidos em cada etapa da geração, permitindo que um LLM emita apenas rótulos permitidos, correspondências de expressões regulares ou JSON válido conforme um esquema.
A decodificação restrita é uma técnica de geração de texto que limita quais tokens um modelo de linguagem pode produzir em cada etapa, garantindo que o resultado final corresponda a um formato obrigatório: um conjunto fixo de rótulos, uma expressão regular, uma gramática ou um JSON Schema. O modelo ainda calcula uma pontuação para cada token do vocabulário. Antes de escolher um token, o decodificador remove todas as opções que violariam o formato. Aplicações que analisam a saída do modelo, como back-ends de API, agentes de IA e pipelines de extração de dados, usam esse recurso para que cada resposta possa ser analisada na primeira tentativa.
Mascaramento de tokens inválidos#
Um modelo de linguagem grande gera texto um token de cada vez. Em cada etapa, ele produz uma pontuação, ou logit, para cada token do vocabulário, e uma softmax converte essas pontuações em probabilidades. A decodificação restrita adiciona uma operação antes da amostragem: os tokens que não podem levar a uma saída válida recebem um logit de menos infinito, o que lhes atribui probabilidade zero, e a probabilidade restante é renormalizada entre os tokens válidos.
import torch
# Raw next-token scores from a model over a toy vocabulary
vocab = ["approved", "rejected", "review", "maybe", "{", "}"]
logits = torch.tensor([1.2, 0.4, 0.9, 2.5, 0.1, 0.3])
# The schema allows only the three status labels at this position
allowed = torch.tensor([True, True, True, False, False, False])
masked_logits = logits.masked_fill(~allowed, float("-inf"))
# Softmax renormalizes probability over the valid tokens only
for name, raw, masked in zip(vocab, logits.softmax(-1), masked_logits.softmax(-1)):
print(f"{name:>9}: {raw:.2f} -> {masked:.2f}")O modelo sem restrições atribui 56% da probabilidade a «maybe». Com a máscara aplicada, «maybe» cai para zero e os três rótulos permitidos dividem a probabilidade proporcionalmente às suas pontuações originais, fazendo com que «approved» suba de 15% para 46%.
Mecanismos de inferência de produção acompanham um estado de restrição durante a geração. Uma lista fixa de opções ou uma expressão regular é compilada em uma máquina de estados finitos. JSON e outros formatos aninhados precisam de uma gramática com pilha, pois uma chave de fechamento só é válida após uma chave de abertura correspondente. Depois de cada token, o decodificador avança o estado e recalcula o conjunto de opções permitidas. A tokenização produz unidades de subpalavras de comprimentos variados; por isso, um único token como "}, pode abranger várias etapas da gramática de uma só vez. Assim, as bibliotecas pré-calculam quais entradas do vocabulário são válidas em cada estado, mantendo baixo o custo por token, mesmo para vocabulários com mais de 100.000 tokens. Em 2023, Brandon Willard e Rémi Louf descreveram essa indexação para expressões regulares e gramáticas livres de contexto em Efficient Guided Generation for Large Language Models, o artigo que deu origem à biblioteca Outlines.
Escolher uma restrição#
A restrição certa corresponde à saída que a aplicação realmente consome. Uma lista de opções funciona bem para classificação e roteamento, quando a resposta precisa ser uma entre algumas strings. Expressões regulares abrangem valores estruturados curtos, como datas, IDs e números de telefone. Gramáticas livres de contexto descrevem SQL, código e linguagens específicas de domínio, e o formato de gramática GBNF do llama.cpp é um exemplo amplamente usado. Para registros com campos nomeados, o JSON Schema especifica chaves obrigatórias, tipos, enums e aninhamento. APIs hospedadas, como OpenAI Structured Outputs, aceitam um esquema e o impõem durante a geração, geralmente com suporte a um subconjunto documentado da especificação completa do JSON Schema.
A descodificação condicionada é muitas vezes confundida com técnicas semelhantes:
- Saídas estruturadas: O objetivo mais amplo de gerar respostas legíveis por máquina, alcançado por meio da decodificação restrita durante a geração ou da validação posterior da saída, com uma nova tentativa em caso de falha.
- Modo JSON: Restringe a saída a JSON sintaticamente válido de qualquer formato, mas ainda é preciso verificar as chaves, os tipos e os valores.
- Engenharia de prompts: Solicita um formato nas instruções, que os modelos seguem na maioria das vezes. Solicitações com restrições de esquema geralmente também descrevem os campos no prompt, para que o modelo saiba o significado de cada um.
- Chamada de funções: Os nomes e argumentos das ferramentas estão entre os alvos mais comuns das restrições de esquema, uma vez que o código que as chama espera nomes de campos exatos.
Compromissos na prática#
Um formato garantido não garante nada sobre o conteúdo. Um esquema pode obrigar {"total": 1290.00} a ser um número, mas esse número pode continuar errado, e um modelo com restrições pode alucinar fluentemente em campos válidos. As aplicações continuam a ter de validar as regras de negócio após a geração.
As restrições também podem reduzir a qualidade das respostas quando levam o modelo a se afastar do texto que escreveria naturalmente. Um esquema que exige que a resposta final seja o primeiro campo não deixa espaço para o raciocínio intermediário, por isso os esquemas costumam colocar um campo de raciocínio ou observações em texto livre antes do campo da resposta. Também é preciso prestar atenção ao comprimento da saída: se a geração atingir o limite de tokens no meio de um objeto, o resultado será inválido, independentemente da restrição. Por isso, solicitações estruturadas definem limites máximos com folga suficiente para toda a estrutura. Esquemas muito grandes ou profundamente recursivos demoram mais para compilar, o que importa em sistemas que criam um esquema novo para cada solicitação.
Aplicações de visão usam o mesmo mecanismo quando um modelo multimodal precisa retornar campos sobre uma imagem. A interface LLM da Ultralytics encaminha os argumentos das solicitações sem alterações para APIs compatíveis com OpenAI; assim, um JSON Schema passado junto com uma solicitação de imagem limita a resposta de um modelo de visão e linguagem a campos como hazard e severity, prontos para serem combinados com as detecções do YOLO26 do mesmo quadro.










