Перейти к содержимому
ПереводыOpenAI и DeepLearning.AI

OpenAI Cookbook: устойчивые промпты и «маховик оценки»

Полный перевод рецепта OpenAI о том, как делать промпты надёжными: цикл «анализ → измерение → улучшение», открытое и осевое кодирование ошибок, автоматические грейдеры, синтетические тесты по измерениям и выравнивание LLM-судьи по TPR и TNR.

Это практическое руководство о том, как с помощью OpenAI Platform без труда сделать свои промпты устойчивыми.

Устойчивый промпт (resilient prompt) — это промпт, который даёт качественные ответы на всём разнообразии возможных входных данных.

Устойчивость промптов — необходимая часть развёртывания ИИ-приложений в продакшене. Без неё промпты могут давать неожиданные результаты на крайних случаях, посредственные ответы в обычных случаях и подрывать эффективность вашего ИИ-приложения.

Чтобы сделать промпты устойчивыми, мы рекомендуем процесс маховика оценки (evaluation flywheel) — методологию, которая позволяет разработчикам постоянно и измеримо улучшать свои ИИ-приложения.

Рецепт рассчитан на предметных экспертов, архитекторов решений, специалистов по данным и ИИ-инженеров, которые хотят повысить общую согласованность и качество своих промптов или разобраться с конкретными крайними случаями в своих ИИ-приложениях.

ИИ-приложения часто кажутся хрупкими. Промпт, который сегодня работает хорошо, завтра может выдавать неожиданные и некачественные результаты. Так происходит потому, что промпты бывают чувствительны к небольшим изменениям во входе пользователя или контексте. Чтобы строить надёжные ИИ-продукты, нужен систематический способ делать промпты устойчивее.

Решение — непрерывный итеративный процесс, называемый маховиком оценки. Вместо того чтобы гадать, что может улучшить промпт («пиши промпт и молись», prompt-and-pray), этот жизненный цикл даёт структурированную инженерную дисциплину для диагностики, измерения и решения проблем.

Маховик состоит из трёх фаз:

  1. Анализ. Понять, как и почему система ошибается, с помощью качественного разбора. Вручную просмотреть и разметить примеры, где модель ведёт себя неправильно, чтобы выявить повторяющиеся типы сбоев.
  2. Измерение. Количественно оценить выявленные типы сбоев и задать базовый уровень. Нельзя улучшить то, что не можешь измерить. Создать тестовый набор данных и построить автоматические оценщики («грейдеры», graders), чтобы оценивать качество системы в больших масштабах.
  3. Улучшение. Вносить точечные улучшения: переписывать промпты, добавлять примеры получше, настраивать компоненты системы. Когда измерение налажено, влияние изменений видно сразу, и можно итерировать, пока доля сбоев не станет приемлемо низкой.

Это непрерывный цикл. По мере улучшения системы появляются новые, более тонкие типы сбоев — и маховик начинает новый оборот. Этот процесс — основная методология построения надёжных и устойчивых ИИ-приложений.

flowchart LR
A["Анализ: читаем ошибки,<br/>размечаем типы сбоев"] --> M["Измерение: тест-набор<br/>и грейдеры, базовый уровень"]
M --> I["Улучшение: правим промпт,<br/>примеры, компоненты"]
I --> A
Маховик оценки (схема перерисована по описанию в оригинале)

Источник схемы в оригинале: Shankar, S., & Husain, H. (2025). Application-Centric AI Evals for Engineers and Technical Product Managers. AI Evals Course Reader.

Чтобы проиллюстрировать процесс оценки, возьмём данные ассистента по аренде квартир, работающего в продакшене.

Он отвечает на вопросы потенциальных арендаторов, например:

  • «Какой площади квартиры?»
  • «Когда можно прийти на просмотр?»

Предположим, в нашем приложении есть конкретный промпт, который мы хотим проанализировать. Начать можно в OpenAI Platform: добавить туда наш промпт и загрузить входные и выходные данные в Dataset (подробнее, как это сделать, — в нашей документации).

[В оригинале — снимок экрана: таблица датасета с колонками входа пользователя и ответа ассистента.]

Когда промпт и трассы (traces) загружены, можно анализировать эффективность промпта.

Чтобы улучшить систему, сначала нужно понять, как она ошибается. Автоматические метрики полезны для отслеживания прогресса, но не могут показать, почему произошёл сбой. Ручной анализ выходов модели — самый эффективный способ диагностировать проблемы и найти идеи для точечных улучшений.

Сердце такого анализа — аннотирование (разметка): присвоение тексту структурированных меток, чтобы классифицировать и понять типы сбоев. Это превращает неструктурированные сбои в конкретный план улучшений. Мы рекомендуем двухшаговый метод из качественных исследований: открытое кодирование (open coding) и осевое кодирование (axial coding).

1. Открытое кодирование: находим типы сбоев

Заголовок раздела «1. Открытое кодирование: находим типы сбоев»

Первый шаг — прочитать выборку неудачных трасс (мы рекомендуем начать примерно с 50) и дать описательную метку каждой найденной ошибке. На этом этапе не беспокойтесь о создании идеальной структурированной классификации. Цель — обнаружение.

В OpenAI Platform для открытого кодирования датасета можно использовать колонки аннотаций. Здесь мы добавляем колонку аннотаций типа Feedback (отзыв) с названием open_coding, чтобы записывать результаты.

[В оригинале — снимок экрана: создание колонки типа Feedback.]

Для нашего ассистента по аренде первые открытые коды могут выглядеть так:

  • «бот предложил время просмотра, которое было недоступно»;
  • «список удобств выдан одним сплошным блоком текста»;
  • «при переносе не отменил исходную запись»;
  • «ссылка на планировку была битой».

Эти конкретные, основанные на данных метки становятся сырьём для следующего шага.

[В оригинале — снимок экрана: датасет после открытого кодирования, у каждой неудачной строки — описание ошибки.]

Вот так выглядит наш датасет после открытого кодирования.

2. Осевое кодирование: структурируем находки

Заголовок раздела «2. Осевое кодирование: структурируем находки»

Когда набор открытых кодов собран, следующий шаг — сгруппировать их в категории более высокого уровня. Это осевое кодирование — процесс поиска связей между первоначальными метками, чтобы получить структурированное понимание основных проблем.

Мы можем сгруппировать открытые коды в заранее определённые осевые коды:

  • Проблема с назначением или переносом просмотра:
    • бот предложил время просмотра, которое было недоступно;
    • при переносе не отменил исходную запись.
  • Ошибка форматирования ответа:
    • список удобств выдан одним сплошным блоком текста;
    • ссылка на планировку была битой.

Чтобы записать это, добавим в датасет новую колонку аннотаций типа Label (метка) с названием axial_coding.

[В оригинале — снимок экрана: колонка axial_coding с выбором категории для каждой строки.]

Эта простая классификация даёт ясную количественную картину главных слабостей системы. Мы можем обнаружить, что 35 % сбоев связаны с назначением просмотров, и только 10 % — ошибки форматирования. Это точно говорит, на чём сосредоточить усилия по улучшению. Подробнее о том, как проводить анализ ошибок, — в этом разборе.

Добавляем надёжности автоматическими грейдерами

Заголовок раздела «Добавляем надёжности автоматическими грейдерами»

Вооружившись классификацией и датасетом, можно начинать автоматизировать маховик оценки. OpenAI Platform поддерживает разные типы грейдеров (в том числе грейдеры на Python и грейдеры на основе LLM), которые можно массово запускать на датасете (подробнее — здесь). Для нашего примера можно построить и запустить LLM-грейдеры для следующего:

  • грейдер форматирования: оценивает, соответствует ли ответ модели нужному формату;
  • грейдер точности доступности: сравнивает доступность (свободные даты и время), которую вернула модель, с эталонным значением, которое вы указали в датасете.

Грейдер форматирования — довольно прямолинейная инструкция.

[В оригинале — снимок экрана: настройка LLM-грейдера форматирования.]

Грейдер точности доступности будет ссылаться на дополнительные входные колонки, которые мы добавили в датасет, чтобы хранить часы работы и доступность по дням.

[В оригинале — снимки экрана: настройка грейдера доступности и колонки с эталонными значениями.]

Когда автоматические грейдеры на месте, можно легко оценить качество при любом изменении системы — новом промпте, новых параметрах модели или недавно обнаруженных крайних случаях.

Подробнее о том, как правильно настроить грейдеры, — в разделе «Выравнивание LLM-судьи» ниже.

Мы определили и классифицировали ошибки и построили оценку, которая автоматизирует наш маховик. На этом этапе можно было бы использовать данные, чтобы вручную менять промпт. Но OpenAI Platform поддерживает автоматический инструмент оптимизации промптов, который ускоряет процесс.

Оптимизатор промптов учитывает сгенерированные выходы, наши собственные колонки аннотаций и грейдеры, чтобы построить улучшенный промпт. Здесь мы построили довольно маленький пример, но на полноценном датасете (скажем, из 50 строк, как мы советовали выше) оптимизатор выдаст новый промпт, который решит многие из выявленных ошибок.

Возможно, нам захочется итерировать дальше: заново разметить новые выходы модели, добавить или доработать грейдеры и снова оптимизировать. Грейдеры и описания колонок аннотаций сохраняются между вкладками, так что, работая, можно и дальше создавать новые версии промпта в новых вкладках. Вкладки также позволяют сравнивать качество разных моделей, так что с помощью грейдеров можно измерить, какая конфигурация параметров модели работает лучше всего.

Этот процесс позволяет со временем улучшать промпт, заранее реагируя на новые ошибки или выход новых моделей.

Расширяем датасет синтетическими данными

Заголовок раздела «Расширяем датасет синтетическими данными»

Основной маховик оценки — ваш главный инструмент улучшения системы. Но бывает, что тестовых данных нужно больше, чем можно собрать из логов продакшена. Генерация синтетических данныхсинтетические данныеEN synthetic data — мощный дополнительный приём для таких ситуаций. Она особенно полезна, если вы хотите подробнее исследовать конкретный тип сбоя, если продукт ещё не выпущен и нужны начальные данные, или если у вас есть гипотеза о слабом месте, но нет реальных примеров, чтобы её проверить.

Если просто попросить LLM «сгенерируй N примеров», часто получается однородный набор тестов. Более структурированный подход — определить ключевые измерения запроса и генерировать данные по их комбинациям, образующим кортежи. Это обеспечивает больше разнообразия и лучшее покрытие тестового набора.

Для нашего ассистента по аренде можно задать такие измерения:

  • Канал: голос, чат, SMS.
  • Намерение: назначение просмотра, ремонт и обслуживание, общая информация и вопросы.
  • Персона: потенциальный жилец, агентство.

Затем их можно скомбинировать в кортеж вроде (Text, Tour Scheduling, Prospective Resident) и попросить LLM сгенерировать конкретные тестовые случаи под этот профиль. Такой структурированный метод создаёт сложные реалистичные сценарии, которые более простой процесс генерации мог бы пропустить.

Кроме того, что меняются основные составляющие запроса, к тестовым случаям можно применять возмущения (perturbations), чтобы сделать их сложнее и реалистичнее. Это значит слегка изменить сгенерированные примеры, чтобы проверить устойчивость системы. Типичные возмущения: добавить нерелевантную информацию, внести ошибки или использовать другой сленг.

Подробнее эта тема разобрана в этом обсуждении.

Автоматический LLM-судья полезен, только если его суждениям можно доверять. Чтобы этого добиться, нужно систематически измерять его качество относительно человека — предметного эксперта (subject-matter expert, SME) — на «золотом» датасете.

Однако большинство тестовых наборов несбалансированны — в них гораздо больше примеров «прошёл», чем «не прошёл». Из-за этого простая точность (accuracy) вводит в заблуждение. Судья, который всегда отвечает «прошёл», может иметь точность 95 %, но ни разу не найдёт ни одного сбоя.

  • Доля истинно положительных (True Positive Rate, TPR): насколько хорошо судья правильно находит сбои?
  • Доля истинно отрицательных (True Negative Rate, TNR): насколько хорошо судья правильно находит успехи?

Цель — получить высокие значения и TPR, и TNR. Это подтверждает, что судья эффективно находит настоящие проблемы и при этом не придирается сверх меры. Процесс измерения использует стандартное разбиение датасета.

  1. Обучающий набор (≈20 %). Его единственная задача — дать примеры few-shot для промпта судьи. Вы выберете из него несколько ясных примеров «прошёл» и «не прошёл» и вставите прямо в промпт, чтобы дать судье хорошую отправную точку.
  2. Валидационный набор (≈40 %). На нём вы итеративно улучшаете судью. Запускаете судью на этом наборе и разбираете случаи, где его решение расходится с решением эксперта. Настраиваете инструкции в промпте судьи, чтобы улучшить и TPR, и TNR.
  3. Тестовый набор (≈40 %). Этот последний, отложенный набор — ваш табель. После настройки запустите судью на нём один раз. Итоговые TPR и TNR подтвердят, что вы не переобучились, и дадут заслуживающую доверия меру качества вашего судьи.

Подробнее о том, как выровнять LLM-судью с экспертами, — в этом обсуждении. Подробнее о том, какую модель использовать в роли судьи для вашего ИИ, — в этом посте.

Этот рецепт даёт базовый рабочий процесс для построения устойчивых промптов, но маховик оценки не останавливается после одного оборота. Следующий шаг — сделать этот процесс основной частью вашей инженерной практики: встроить грейдеры в конвейер CI/CD и отслеживать данные продакшена, чтобы находить новые типы сбоев.

Кроме того, мир оценки ИИ глубок и полон трудностей, которые мы не смогли здесь осветить. Выстраивая свою стратегию оценки, вы, скорее всего, столкнётесь с более сложными вопросами, например:

  • Как убедить команду вкладываться в оценку?
  • Почему бинарная оценка (прошёл / не прошёл) часто лучше шкалы от 1 до 5?
  • Как лучше всего отлаживать сложную трассу многоходового диалога?
  • Как подходить к оценке своей RAG-системы?
  • Как этот процесс адаптируется к агентным системам?

Для дальнейшего изучения рекомендуем этот FAQ об эвалах.


Что сделать руками (добавлено переводчиком)

Заголовок раздела «Что сделать руками (добавлено переводчиком)»
  1. Возьмите свой RAG-бот из урока 8.2.1 или бота из практики урока 8.4.1. Соберите 30–50 ответов, где он ошибся, и проведите открытое кодирование в обычной таблице: одна колонка — вход, вторая — ответ, третья — ваша заметка.
  2. Сгруппируйте заметки в 3–5 осевых категорий и посчитайте доли. Какая категория самая большая?
  3. Для самой большой категории напишите грейдер: сначала детерминированный (регулярное выражение, сравнение с эталоном), если не получается — LLM-судью с ответом «прошёл / не прошёл».
  4. Разметьте вручную 40 ответов, разбейте на 20/40/40 % и посчитайте TPR и TNR своего судьи на тестовой части.
  5. Сгенерируйте синтетические тесты по трём измерениям, как в примере выше, и прогоните систему до и после правки промпта. Решение «выпускать ли» примите по статистике из урока 8.4.1.