сеньорчикОткрыть в Telegram
← вся теориятеория к собесу · LLM и RAG

Промптинг и структурный вывод

Зачем это спрашивают

Промптинг в проде - инженерия, а не заклинания: структурный вывод, температура, регрессионные тесты. Вопрос-детектор: «как получить от модели надёжный JSON» - по ответу видно, падал ли твой парсер на „Вот ваш JSON:“.

// Промпт это код: версионируется, тестируется, имеет регрессии.

Few-shot и chain-of-thought

Few-shot: примеры «вход → выход» прямо в промпте задают формат надёжнее любых словесных описаний. Это in-context learning - веса не меняются, модель подхватывает паттерн из контекста.

Chain-of-thought - «рассуждай по шагам» - поднимает качество на задачах рассуждения; заметно работает у достаточно крупных моделей.

// Ловушка few-shot: модель копирует всё, включая перекос примеров. Все примеры позитивного класса, и классификатор внезапно «всегда позитивен».

in-context learning
обучение из примеров в промпте, без изменения весов
self-consistency
несколько цепочек рассуждения → мажоритарный ответ

Структурный вывод: JSON без слёз

Иерархия надёжности: просьба «верни JSON» < few-shot с примерами формата < JSON-схема с валидацией и ретраем < constrained decoding / функции API, где грамматика формата гарантирована генерацией.

На своей стороне всегда: валидатор схемы и ретрай с сообщением об ошибке. Прод, парсящий свободный текст без валидации, падает на первом же вежливом предисловии модели.

// Температура - под задачу: 0 для экстракции и классификации (детерминизм и стабильный формат), выше - для генерации идей. 0.8 на извлечении полей - «творческие» значения.

constrained decoding
генерация, ограниченная грамматикой/схемой формата
температура
разброс сэмплирования: 0 - детерминизм, выше - разнообразие

Промпт это код

Структура рабочего промпта: роль и задача, контекст, формат ответа, ограничения, примеры. Инструкции - явные и позитивные: «выведи только JSON» работает лучше «не пиши лишнего».

Промпт версионируется и тестируется: набор кейсов с ожидаемыми ответами, прогон на каждое изменение. «Поправил слово - сломал прод» без тестов не видно вообще.

// Дорогой приём для точности: self-consistency - сэмплировать несколько цепочек рассуждения и взять мажоритарный ответ; на математике и логике даёт ощутимый прирост.

Как отвечать: «Как получить от модели гарантированный JSON?»

Слоями, от гарантий к страховкам. Лучший вариант - constrained decoding или tool/function calling: формат гарантируется самой генерацией по схеме. Если API этого не даёт - жёсткая JSON-схема в промпте, few-shot пример и температура 0. И в любом случае на моей стороне валидатор схемы с ретраем: при невалидном ответе возвращаю модели ошибку валидации и прошу исправить. Плюс регрессионный набор кейсов на каждое изменение промпта - формат имеет свойство ломаться от невинных правок.

Иерархия от гарантированного к вероятностному и обвязка на своей стороне - инженерный ответ вместо «попросить получше».

На чём валят

  • Парсить JSON из свободного текста без валидатора и ретрая - прод падает на «Вот ваш JSON:».
  • Few-shot с однобокими примерами - модель копирует перекос.
  • Температура 0.8 на извлечении полей - плавающий формат и творческие значения.
  • Менять промпт в проде без регрессионных кейсов - улучшил один случай, сломал десять.

Проверьте себя

Пять вопросов из банка по этой подтеме. Всего их 12, остальные разбираются в тренажёре.

  1. #prompting_structured1 / 5
    Приложению нужен строго JSON от LLM для парсинга. Что надёжнее «попросить в промпте вернуть JSON»?
    A)Structured output / constrained decoding: генерировать строго по JSON-схеме на уровне декодирования
    B)Повысить температуру, чтобы JSON получался разнообразнее
    C)Просить модель писать весь ответ заглавными буквами
    D)Ничего лучше нет, вежливая просьба в тексте промпта — это доступный способ добиться JSON а обеспечить валидный JSON от модели иным путём не получится
    показать ответ и разбор
    +A)Structured output / constrained decoding: генерировать строго по JSON-схеме на уровне декодирования

    // разбор: Просьба в промпте не гарантирует валидный JSON — модель может добавить текст, сломать кавычки, забыть поле. Structured output / constrained decoding ограничивает генерацию грамматикой/схемой на уровне выбора токенов (JSON mode, function calling, грамматики) — на выходе всегда синтаксически валидная структура. Это снимает хрупкий парсинг и ретраи. Схему всё равно валидируют на стороне приложения.

  2. #prompting_structured2 / 5
    Небольшая переформулировка промпта заметно меняет качество ответов. Что это говорит и что делать?
    A)Это сложно, формулировка промпта на результат не влияет
    B)Надо просто повысить температуру сэмплирования
    C)LLM чувствительна к формулировке: промпты надо тестировать на наборе кейсов и версионировать, а не подбирать на глаз
    D)Модель сломана, её нужно немедленно заменить на другую
    показать ответ и разбор
    +C)LLM чувствительна к формулировке: промпты надо тестировать на наборе кейсов и версионировать, а не подбирать на глаз

    // разбор: Prompt sensitivity — реальное свойство: формулировка, порядок, разделители, формат примеров влияют на выход, потому что меняют условное распределение. Вывод не «модель сломана», а «промпт — это артефакт, который надо инженерить»: держать набор тест-кейсов, мерить изменения, версионировать промпты как код, не полагаться на разовый подбор. Температура тут ни при чём.

  3. #prompting_structured3 / 5
    Зачем в чат-моделях разделяют system-, user- и assistant-роли?
    A)Это чисто косметическое разделение ролей в интерфейсе, не имеющее вообще никакого эффекта на поведение модели
    B)Чтобы модель отвечала пользователю ощутимо быстрее
    C)Чтобы экономить токены на разметке сообщений
    D)System задаёт устойчивые правила/роль поверх диалога, user — запрос; модель обучена приоритезировать system
    показать ответ и разбор
    +D)System задаёт устойчивые правила/роль поверх диалога, user — запрос; модель обучена приоритезировать system

    // разбор: Роли структурируют контекст: system несёт устойчивые инструкции/персону/правила, user — конкретный запрос, assistant — прошлые ответы. Chat-модели дообучены трактовать system с более высоким приоритетом, поэтому туда кладут политику и формат. Это не косметика — рычаг управления поведением и (частичной) защиты от переопределения правил пользователем. Полной гарантии приоритета нет (см. джейлбрейки).

  4. #prompting_structured4 / 5
    В длинный промпт кладут инструкцию, потом много контекста. Где разместить ключевую инструкцию и почему?
    A)Это не важно, поскольку позиция инструкции в промпте на внимание модели не влияет
    B)Обязательно ровно в геометрическом центре всего контекста
    C)В начале и/или в конце: модель хуже использует середину длинного контекста (lost in the middle)
    D)В самом конце промпта и не в начале
    показать ответ и разбор
    +C)В начале и/или в конце: модель хуже использует середину длинного контекста (lost in the middle)

    // разбор: «Lost in the middle»: модели надёжнее используют информацию в начале и конце длинного контекста, а помещённое в середину — теряют. Поэтому ключевую инструкцию и важные документы ставят с краёв, критичные факты дублируют/выносят в конец, а реранкинг располагает лучшие чанки по краям. Позиция реально влияет — суть не в центре буквально, а в «не хорони важное в середине».

  5. #prompting_structured5 / 5
    Один и тот же большой system-промпт шлётся в тысячах запросов. Как срезать стоимость/латентность?
    A)Никак, каждый запрос считается с нуля
    B)Prompt caching: движок кэширует KV-состояние общего префикса, и повторный префикс не пересчитывается
    C)Поднять температуру, чтобы ответы начали кэшироваться
    D)Уменьшить размер словаря токенизатора модели
    показать ответ и разбор
    +B)Prompt caching: движок кэширует KV-состояние общего префикса, и повторный префикс не пересчитывается

    // разбор: Если у многих запросов общий длинный префикс (system-промпт, инструкции, справочник), prompt caching переиспользует уже посчитанное KV-состояние этого префикса: prefill повторного префикса пропускается, платится только за новый хвост — дешевле и быстрее (меньше TTFT). Работает для стабильного префикса в начале; поэтому неизменное кладут в начало, переменное — в конец.

дальше

Теорию прочитали. Навык ставится повторением

В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.