В последнее время я много работаю с проектами вокруг ИИ. Одной из важных задач в рамках реализации ИИ-проектов является интеграция с LLM. При работе с LLM, естественно, приходится учитывать особенности данной технологии, одной из которых является то, что модель выдает непредсказуемый текстовый ответ, который сложно поместить в надёжный пайплайн. И для того чтобы обуздать произвольный характер ответа LLM, подойдет решение под названием
Structured Output. Это подход, который заставляет модель отвечать строго по заданной
схеме, превращая «рандомайзер» в предсказуемый API. Ниже зафиксирую краткий гайд по четырём способам реализации Structured Output, от простых до более продвинутых.
Еще раз,
Structured Output — это подход, который объявляет для LLM строгий контракт ответа, например: в формате предварительно заданной JSON-схемы. В результате чего мы получаем фиксированный структурированный формат ответа, на базе которого можем спокойно строить привычные пайплайны с дальнейшими манипуляциями над данными, как в случае при работе с традиционным REST API.
#1. Первым, так называемым, базовым способом "в лоб" будет объявление
структуры в промте + реализация стратегии ретраев при валидации ответа LLM: если ответ LLM не будет соответствовать заданной "маске", то мы будем делать повторный запрос на повторную генерацию. Готовую реализацию данного подхода можно найти в таких библиотеках, как
Instructor.
#2. Второй способ это использование
BAML. По своей сути это развитие первого подхода с важным дополнением в виде Schema-Aligned Parsing (SAP). SAP — это «мягкий» парсер, который исправляет типовые ошибки в заданном формате схемы ответа, например в JSON это могут быть забытые скобки и запятые, неверное экранирование, лишний текст до/после JSON.
#3. Третьим рассмотрим уже не просто способ по обработке ответа LLM, а то, как не только через промпт влиять на сам процесс генерации.
Constrained Decoding — это способ про то, как не просить модель ответить правильно, а не дать ей ответить неправильно. Работает это следующим образом: LLM генерирует ответ токен за токеном, но на каждом шаге библиотека (например,
Outlines) "обнуляет вероятность" всем остальным токенам, которые нарушили бы генерацию заданной схемы на текущем шаге, на каждом шаге модель может выбрать только допустимый вариант токена (символа).
#4. И в заключении отмечу
Scheme-Guided Reasoning (SGR). Суть этого способа заключается в том, чтобы объединить силу Chain-of-Thought и структурированного вывода, тем самым заставить модель рассуждать внутри заранее заданной схемы. Как это выглядит: допустим, вы проектируете JSON-схему, которая отражает экспертный чеклист или логику решения задачи. Далее модель вынуждена заполнять поля последовательно, что в свою очередь гарантирует прохождение всех шагов рассуждения и позволяет валидировать промежуточные результаты.
#AI #LLM