У нейросетей есть замечательное свойство.
В понедельник ты находишь почти идеальный промпт. Модель понимает задачу с полуслова, пишет нормальный текст, не лезет куда не просили и вообще ведёт себя как сотрудник месяца. Ты радостно сохраняешь запрос с названием:
ФИНАЛЬНЫЙ ПРОМПТ ТОЧНО РАБОТАЕТ.txt
Во вторник вставляешь его снова.
И получаешь какую-то хрень.
Структура другая. Важное требование проигнорировано. Вместо пяти вариантов — четыре. Стиль вдруг стал похож на корпоративную методичку. А когда просишь исправить, нейросеть ещё и уверенно объясняет, почему именно так было лучше.
Первая мысль понятна:
Вчера же работало. Что они там опять сломали?
Иногда действительно что-то поменялось. Но довольно часто никто ничего не ломал.
Одинаковый промпт вообще не обязан давать одинаковый результат.
И это не баг в привычном смысле.
Нейросеть не достаёт готовый ответ из ящика
Обычная программа ведёт себя привычно.
В калькуляторе:
2 + 2
Сегодня — 4.
Завтра — 4.
После обновления Windows, скорее всего, тоже 4. Если однажды получится 17, мы вполне обоснованно начнём нервничать.
Языковая модель устроена иначе. Она генерирует ответ последовательно, на каждом шаге оценивая вероятные продолжения текста. Из нескольких подходящих вариантов выбирается один, затем на его основе строится следующий кусок и так далее.
Поэтому даже один ранний выбор способен через несколько абзацев привести к совсем другой версии текста.
OpenAI прямо пишет в документации для API, что генерация по умолчанию недетерминирована: одинаковые запросы могут возвращать разные ответы. Anthropic описывает то же самое и отдельно отмечает, что даже при temperature = 0 абсолютная идентичность ответов не гарантируется. (OpenAI Developers)
То есть перед нами не принтер.
Скорее очень образованный человек, которого два раза попросили рассказать одну историю.
Смысл будет похож.
Фразы — уже не обязательно.
А что за temperature, которую постоянно советуют уменьшить?
У языковой модели обычно есть параметры, влияющие на выбор продолжения.
Один из самых известных — temperature.
Упрощённо: высокая температура позволяет модели чаще выбирать менее очевидные варианты. Получается больше разнообразия, неожиданности и творчества. Низкая подталкивает её к наиболее вероятным продолжениям, поэтому ответы становятся стабильнее и консервативнее. Именно так этот параметр описывает Anthropic в документации Claude. (Claude Platform Docs)
Для художественного рассказа разнообразие может быть плюсом. Для задачи:
Верни мне JSON строго из шести полей
творческий порыв уже немного мешает.
Поэтому в автоматизациях температуру часто снижают.
Но кнопки:
НЕ ТУПИТЬ И ВСЕГДА ОТВЕЧАТЬ ОДИНАКОВО
там всё равно нет.
Даже минимальная случайность на одном шаге может дальше изменить всю цепочку.
Более того, ваш «одинаковый промпт» часто вообще не одинаковый
Вот это особенно легко не заметить.
Представим, что пользователь пишет:
Составь пять рекламных заголовков для этого продукта.
Вчера перед этой фразой в разговоре обсуждали молодую аудиторию, низкую цену и рекламу ВКонтакте.
Сегодня тот же запрос отправили после двадцати сообщений о премиальном позиционировании.
Текст последней команды абсолютно одинаковый.
Реальный вход модели — нет.
Модель видит не только последнее предложение. На ответ влияет доступный ей контекст разговора, системные инструкции, дополнительные данные, подключённые инструменты и всё остальное, что приложение передало вместе с запросом.
Поэтому один и тот же промпт в пустом чате и в диалоге на сто сообщений — это фактически две разные задачи.
Я на автоматизациях постоянно стараюсь это держать в голове. Потому что очень легко сказать:
«Мы же ничего не меняли!»
А потом обнаружить, что перед основным запросом добавили результаты исследования на сорок тысяч знаков.
Ну да. Почти ничего.
😁
Особенно весело с длинным контекстом
Допустим, у нас есть огромная инструкция.
Там стиль.
Запреты.
Описание продукта.
Примеры.
Аудитория.
Формат.
База знаний.
Двадцать предыдущих сообщений.
И где-то примерно на тридцать седьмой странице написано:
Никогда не предлагай клиенту скидку самостоятельно.
Человек воспринимает документ как набор чётких правил.
Для модели это большой массив контекста, внутри которого разные фрагменты конкурируют за внимание в конкретной задаче.
Если правило критическое, лучше не надеяться, что оно просто когда-то упоминалось. Его полезнее вынести ближе к месту принятия решения, сформулировать однозначно и при необходимости проверить кодом.
Поэтому хороший промпт — это не максимальное количество текста.
Иногда после сокращения инструкции система начинает работать лучше, потому что важные требования перестают тонуть среди полезных, но второстепенных подробностей.
Бывает и так, что модель действительно поменялась
Вот тут подозрительный пользователь иногда совершенно прав.
В API разработчики могут работать либо с именем модели, либо с конкретной закреплённой версией — snapshot. OpenAI прямо предлагает snapshots именно для случаев, когда нужно зафиксировать версию модели и получить более стабильное поведение. (OpenAI Developers)
У Anthropic подход похожий: документация отдельно описывает закреплённые версии моделей и правила работы идентификаторов. Для современных Claude конкретные model ID привязаны к определённому snapshot, а у более старых поколений некоторые алиасы могли указывать на датированную версию. (Claude Platform Docs)
Зачем вообще это понадобилось?
Потому что для обычного пользователя улучшение модели звучит прекрасно:
Стала умнее!
Для разработчика производственной системы звучит немного иначе:
А она завтра точно не начнёт иначе трактовать мой промпт?
Представьте, у вас сто тысяч автоматических операций в месяц.
Изменилось всего 2% поведения.
Для человека это почти незаметно.
Для бизнеса — уже две тысячи случаев.
Сид немного помогает. Но тоже не магия
В некоторых API можно задавать seed — условное начальное значение для случайного выбора.
OpenAI рекомендует для более воспроизводимых результатов сохранять одинаковыми seed, сам промпт, температуру и остальные параметры. При совпадении этих условий ответы становятся значительно стабильнее. Но документация отдельно предупреждает: полная детерминированность всё равно не гарантируется. (OpenAI Developers)
Там есть ещё интересная штука — system_fingerprint.
Она позволяет разработчику заметить, что изменилась серверная конфигурация, связанная с генерацией. Если fingerprint стал другим, результаты тоже могут начать отличаться даже при прежних настройках. (OpenAI Developers)
То есть производитель буквально говорит разработчику:
Мы дадим тебе инструменты приблизиться к повторяемости. Но обещать математически идентичный ответ каждый раз не будем.
И это совершенно нормальная позиция для генеративной модели.
Иногда виноват вообще не ИИ, а сам промпт
Есть прекрасный тип запросов:
Сделай хороший продающий текст.
Вчера модель написала то, что человеку понравилось.
Сегодня — то, что не понравилось.
Вывод:
модель деградировала.
А что означает «хороший»?
Для кого?
Какая цель?
Какой канал?
Какой объём?
Нужна продажа прямо сейчас или прогрев?
Можно использовать агрессивный CTA?
Нужен экспертный тон или разговорный?
Все эти решения модель вынуждена принять самостоятельно.
Вчера она выбрала один допустимый путь.
Сегодня другой.
Оба формально соответствуют запросу.
Чем больше решений мы оставляем модели на усмотрение, тем выше вариативность результата. Поэтому для производственного процесса лучше писать не:
Сделай красиво.
А задавать критерии:
аудитория такая;
задача такая;
объём такой;
структура такая;
обязательно раскрыть три тезиса;
вот это запрещено;
результат принимается, если выполнены такие условия.
Творчества меньше.
Повторяемости больше.
Для фабрики контента это обычно хороший обмен.
Поиск и внешние инструменты добавляют ещё один слой хаоса
Сейчас современные модели всё чаще работают не только со своими внутренними знаниями.
Они могут сходить в поиск.
Получить документы.
Вызвать API.
Прочитать базу знаний.
Посмотреть данные из CRM.
И тогда даже при полностью одинаковом промпте окружающий мир уже мог измениться.
Вчера поиск выдал источники А, Б и В.
Сегодня — А, Г и Д.
Вчера товар был на складе.
Сегодня закончился.
Вчера в базе клиента было три сделки.
Сегодня четыре.
На выходе закономерно появляется другой ответ.
Это особенно важно при тестировании агентов. Нельзя честно сравнивать две генерации, если между ними поменялись входные данные, а потом заявлять:
Нейросеть нестабильна.
Сначала надо убедиться, что мы действительно повторили эксперимент.
Поэтому тестировать промпт один раз почти бессмысленно
Вот это правило я бы вообще написал крупно во всех инструментах автоматизации.
Допустим, мы придумали новый промпт для ИИ-продавца.
Прогнали один тест.
Он великолепен.
Не задаёт лишних вопросов.
Вовремя делает handoff.
Не придумывает цены.
Можно запускать?
Нет.
Мы пока доказали только:
один раз всё получилось.
Нужно гонять разные входы.
Короткий клиент.
Болтливый.
Агрессивный.
Тот, кто отвечает не на вопрос.
Тот, кто сообщил всю необходимую информацию первой фразой.
Тот, кто дважды поменял решение.
Тот, кто спросил то, чего нет в базе знаний.
Причём каждый сценарий желательно запускать несколько раз.
Потому что production-промпт должен быть хорош не в лучшем проходе.
Он должен быть приемлемым в распределении проходов.
Вот почему evals становятся важнее «магического промпта»
Раньше вокруг нейросетей было много почти шаманской культуры:
добавь «ты эксперт с двадцатилетним стажем»;
напиши «думай пошагово»;
поставь слово IMPORTANT заглавными буквами;
попроси модель дать себе 500 долларов чаевых.
Какие-то приёмы действительно влияли на результат. Некоторые постепенно становились ненужными по мере улучшения моделей.
Но для серьёзной системы нужен другой подход.
Не искать заклинание.
А собрать набор тестовых задач и автоматически измерять:
правильно ли выполнено требование;
не нарушен ли запрет;
есть ли нужные поля;
не выдуманы ли данные;
соответствует ли результат формату;
дошёл ли процесс до нужного состояния.
Тогда после изменения промпта или модели мы можем сказать не:
«На глаз вроде стало лучше».
А:
«Было 84% успешных проходов, стало 93%».
Это уже инженерия.
Для критических задач я бы вообще не требовал одинакового текста
Звучит парадоксально, но мне часто не нужно, чтобы модель каждый раз отвечала одинаковыми словами.
Мне нужно, чтобы она стабильно выполняла правило.
Например, покупатель спрашивает цену, которой нет в базе.
Сегодня агент отвечает:
Точную стоимость лучше уточнить у специалиста.
Завтра:
У меня нет подтверждённой цены по этому варианту, передам вопрос менеджеру.
Тексты разные.
Поведение одинаковое.
Оба ответа хорошие.
А вот если третий раз модель говорит:
Такой вариант обычно стоит около 85 тысяч,
у нас проблема.
То есть воспроизводимость в реальной автоматизации — это не обязательно:
всегда одно и то же предложение.
Гораздо полезнее:
всегда соблюдаются одни и те же бизнес-ограничения.
И самые важные из них я вообще предпочитаю контролировать не промптом, а программой.
Поэтому иногда нейросеть «тупит» совершенно честно
Мы привыкли обращаться с ней как с обычной программой:
Я дал тот же запрос. Почему результат другой?
Потому что это другой класс программ.
Генеративная модель хороша именно благодаря тому, что не обязана работать как жёсткий справочник соответствий «вход → единственный выход».
Если заставить её всегда выдавать строго один ответ, мы одновременно убьём значительную часть того, за что вообще любим нейросети: гибкость, разнообразие формулировок, способность подстроиться под контекст и находить неожиданные варианты.
Поэтому задача разработчика не в том, чтобы превратить LLM в калькулятор.
Калькулятор уже изобрели.
Задача — оставить модели свободу там, где она полезна, и убрать её там, где от неё начинаются проблемы.
Текст статьи может немного отличаться.
JSON для бухгалтерии — лучше не надо.
Шутка в рекламном посте может быть неожиданной.
Цена в коммерческом предложении — категорически нет.
И если вчера ваш прекрасный промпт дал другой ответ, это ещё не означает, что нейросеть сломалась.
Иногда она просто сделала именно то, для чего была создана:
выбрала другой вариант из нескольких возможных.
А вот был ли этот вариант нам нужен — уже вопрос не к магии искусственного интеллекта.
А к тому, насколько хорошо мы построили систему вокруг него.