Constrained Decoding
Декодирование с ограничениями маскирует недопустимые токены на каждом шаге генерации, поэтому LLM может выдавать только разрешённые метки, соответствия регулярным выражениям или JSON, соответствующий схеме.
Ограниченное декодирование — это метод генерации текста, который ограничивает токены, доступные языковой модели на каждом шаге, чтобы итоговый результат гарантированно соответствовал заданному формату: одному из фиксированного набора меток, регулярному выражению, грамматике или JSON Schema. Модель по-прежнему оценивает каждый токен в своём словаре. Перед выбором токена декодер удаляет все варианты, которые нарушили бы формат. Приложения, разбирающие вывод модели, например серверные части API, ИИ-агенты и конвейеры извлечения данных, используют этот метод, чтобы каждый ответ разбирался с первой попытки.
Маскирование недопустимых токенов#
Большая языковая модель генерирует текст по одному токену за раз. На каждом шаге она выдаёт оценку, или логит, для каждого токена в своём словаре, а функция softmax преобразует эти оценки в вероятности. Ограниченное декодирование добавляет одну операцию перед семплированием: токены, которые не могут привести к допустимому результату, получают логит, равный минус бесконечности, а значит, нулевую вероятность; вероятности оставшихся допустимых токенов перенормируются.
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}")В модели без ограничений на вариант «возможно» приходится 56% вероятности. После применения маски вероятность варианта «возможно» падает до нуля, а три разрешённые метки делят вероятность пропорционально исходным оценкам, поэтому вероятность варианта «одобрено» возрастает с 15% до 46%.
Промышленные механизмы инференса отслеживают состояние ограничений по мере генерации. Фиксированный список вариантов или регулярное выражение компилируется в конечный автомат. Для JSON и других вложенных форматов нужна грамматика со стеком, потому что закрывающая фигурная скобка допустима только после соответствующей открывающей. После каждого токена декодер обновляет состояние и пересчитывает допустимое множество. Токенизация разбивает текст на субсловные фрагменты разной длины, поэтому один токен, например "},, может охватывать сразу несколько шагов грамматики. Поэтому библиотеки заранее вычисляют, какие элементы словаря допустимы в каждом состоянии; благодаря этому стоимость обработки каждого токена остаётся небольшой даже при словаре более чем из 100 000 токенов. В 2023 году Брэндон Уиллард и Реми Луф описали такую индексацию для регулярных выражений и контекстно-свободных грамматик в статье Эффективная управляемая генерация для больших языковых моделей, на которой основана библиотека Outlines.
Выбор ограничений#
Подходящее ограничение соответствует выводу, который действительно использует приложение. Список вариантов подходит для классификации и маршрутизации, когда ответ должен быть одной из нескольких строк. Регулярные выражения подходят для коротких структурированных значений, например дат, идентификаторов и телефонных номеров. Контекстно-свободные грамматики описывают SQL, код и предметно-ориентированные языки; формат грамматик GBNF в llama.cpp — широко используемый пример. Для записей с именованными полями JSON Schema задаёт обязательные ключи, типы, перечисления и вложенность. Размещённые API, например структурированные выходные данные OpenAI, принимают схему и применяют её во время генерации, обычно поддерживая документированное подмножество полной спецификации JSON Schema.
Декодирование с ограничениями часто путают с близкими методами:
- Структурированные выходные данные: Более широкая цель — получать машиночитаемые ответы. Её достигают либо ограниченным декодированием во время генерации, либо последующей проверкой результата и повторной попыткой в случае ошибки.
- Режим JSON: Ограничивает вывод синтаксически корректным JSON произвольной структуры, поэтому ключи, типы и значения всё равно нужно проверять.
- Промпт-инжиниринг: В инструкциях запрашивается определённый формат, которому модели следуют в большинстве случаев. В запросах с ограничениями по схеме поля обычно также описывают в промпте, чтобы модель понимала назначение каждого из них.
- Вызов функций: Имена инструментов и аргументы — одни из самых распространённых целей ограничений на основе схем, поскольку вызывающий код ожидает точные имена полей.
Практические компромиссы#
Гарантия формата ничего не гарантирует в отношении содержания. Схема может требовать, чтобы {"total": 1290.00} было числом, но число всё равно может быть неправильным. Кроме того, модель с ограничениями может связно галлюцинировать, заполняя допустимые поля. После генерации приложения всё равно должны проверять соблюдение бизнес-правил.
Ограничения также могут снижать качество ответа, если уводят модель от текста, который она написала бы естественным образом. Если схема требует поместить итоговый ответ в первое поле, для промежуточных рассуждений не остаётся места, поэтому в схемах часто размещают поле для свободных рассуждений или заметок перед полем ответа. Нужно учитывать и длину вывода: если генерация достигает лимита токенов посреди объекта, результат будет недопустимым независимо от ограничения, поэтому в структурированных запросах задают максимальную длину с запасом на всю структуру. Очень большие или глубоко рекурсивные схемы компилируются дольше, что важно для систем, создающих новую схему для каждого запроса.
В приложениях компьютерного зрения применяется тот же механизм, когда мультимодальная модель должна вернуть поля об изображении. Интерфейс LLM Ultralytics передаёт аргументы запроса в API, совместимые с OpenAI, без изменений, поэтому JSON Schema, переданная вместе с запросом изображения, ограничивает ответ модели, работающей с изображениями и текстом, задавая такие поля, как hazard и severity, которые готовы к объединению с результатами детекции YOLO26 для того же кадра.










