Температура, top-p и почему воспроизводимости не бывает
Как модель на самом деле выбирает следующий токен, что делают ручки сэмплирования и почему нулевая температура не даёт гарантии повторяемости.
Просьба, которую я слышу почти на каждом внедрении: «сделайте, чтобы ответ был одинаковым». Обычно за ней стоит разумное желание — прогнать тесты и сравнить результат до и после правки.
Ответ неудобный: одинаковым он не будет. Можно снизить разброс, но нельзя получить гарантию, и понимание, почему так, экономит недели попыток.
Что модель делает на каждом шаге
Модель не выбирает слово. Она выдаёт распределение вероятностей по всему словарю — числа для каждого из десятков тысяч токенов. Из этого распределения кто-то должен выбрать один токен, и этот кто-то — код сэмплирования, а не сама модель.
Температура делит логиты перед нормировкой. Меньше единицы — распределение становится острее, вероятный вариант ещё вероятнее. Больше — площе, шансы у редких растут.
top-p (его же зовут nucleus) отсекает хвост: оставляет минимальный набор токенов, у которых суммарная вероятность достигает p. При 0.9 редкие варианты просто не рассматриваются.
top-k делает то же грубее — оставляет фиксированное число вариантов независимо от того, как распределены вероятности.
Почему ноль не спасает
При температуре ноль сэмплер должен выбирать самый вероятный токен, и кажется, что результат обязан повторяться. На практике не повторяется, и причин несколько.
Арифметика с плавающей точкой не ассоциативна. Результат сложения зависит от порядка, а порядок зависит от того, как задача разложилась по вычислителям. Разложение меняется от загрузки, размера батча и версии библиотек. Когда два токена почти равны по вероятности, разница в последнем знаке решает, какой из них «самый вероятный».
Батчинг. На стороне провайдера ваш запрос считается вместе с чужими. Состав батча меняется от вызова к вызову, а вместе с ним — порядок операций.
Версия модели меняется без вашего участия. Даже если всё вышеперечисленное удалось зафиксировать, за одним и тем же именем модели со временем стоит другой набор весов. Воспроизводимость, на которую нельзя опереться во времени, для разбора инцидента бесполезна.
Отсюда мой основной тезис: воспроизводимость не является свойством модели, и строить на ней проверку нельзя.
Что делать вместо
Проверять не совпадение текста, а выполнение требований.
Вместо «ответ равен эталону» — «ответ содержит все обязательные поля», «ссылки ведут на существующие документы», «сумма в ответе совпадает с суммой во входных данных», «формат разбирается схемой». Такие проверки переживают и смену версии, и разброс сэмплирования, потому что меряют то, что вам действительно нужно.
Там, где нужна именно повторяемость — например, чтобы одинаковый вход давал одинаковый счёт, — правильный инструмент не температура, а кеш: сохранить ответ и переиспользовать его для того же входа. Это даёт настоящую гарантию, а не статистическую.
Как я выставляю ручки
Держу простое разделение, и оно почти всегда оказывается верным.
Извлечение данных, классификация, приведение формата — температура низкая, top-p низкий. Здесь разнообразие вредно: правильный ответ один.
Тексты для людей — температура умеренная. На нуле формулировки становятся однообразными и узнаваемо машинными; небольшой разброс тут работает на качество.
Ручки трогаю по одной. Крутить температуру и top-p одновременно — верный способ не понять, что именно помогло.
Условие несогласия
Если ваш выход — свободный текст, который читает и правит человек, всё это неважно. Разброс между двумя черновиками не имеет значения, когда оба всё равно пойдут в редактуру.
Разговор про воспроизводимость начинается там, где выход уходит дальше по конвейеру без человека.
Чего я делать не стал бы
Не стал бы объяснять заказчику разброс словами «модель творческая». Это звучит как оправдание и мешает договориться о настоящем критерии приёмки.
Не стал бы фиксировать seed и считать вопрос закрытым. Seed убирает одну из причин разброса и оставляет остальные — это полезная гигиена, а не гарантия.