Проблема: ваша модель превратилась в попугая
Вы скачали свежайшую Llama 3.2 90B, запустили через llama.cpp, задали вопрос... и получили ответ. Повторили запрос — тот же самый ответ, слово в слово. Ещё раз — опять идентично. Похоже на баг, но на самом деле это стандартное поведение. И оно сводит с ума всех, кто хочет протестировать модель или нуждается в разнообразии ответов.
Ключевая мысль: Локальные LLM по умолчанию детерминированы. Это не ошибка, а следствие конкретных значений параметров генерации. Понимание этих настроек — ключ к управлению творчеством модели.
Три кита случайности: seed, temperature и top_p
Представьте, что генерация текста — это выбор следующего слова из огромного списка кандидатов. Модель присваивает каждому слову вероятность. Параметры seed, temperature и top_p — это три рычага, которые управляют тем, как мы делаем этот выбор.
1 Seed: отправная точка случайности
Что это: Число, которое инициализирует генератор псевдослучайных чисел. Одинаковый seed + одинаковые входные данные = абсолютно одинаковый вывод.
Зачем нужен: Для воспроизводимости. Хотите точно повторить эксперимент или отладить промпт? Установите конкретный seed. Хотите разнообразия? Установите seed = -1 (или 0 в некоторых API). Это заставит систему использовать случайное seed на основе времени.
# Пример с llama-cpp-python (актуально на январь 2026)
from llama_cpp import Llama
llm = Llama(model_path="./llama-3.2-90b-vision-q4_K_M.gguf")
# Детерминированный режим (всегда один ответ)
output1 = llm("Напиши хайку про DevOps", seed=42, temperature=0.7)
output2 = llm("Напиши хайку про DevOps", seed=42, temperature=0.7)
# output1 и output2 будут идентичны
# Неопределённый режим (разные ответы)
output3 = llm("Напиши хайку про DevOps", seed=-1, temperature=0.7)
output4 = llm("Напиши хайку про DevOps", seed=-1, temperature=0.7)
# output3 и output4, скорее всего, будут разными2 Temperature: регулятор креативности
Что это: Параметр, который "сглаживает" или "заостряет" распределение вероятностей перед выбором слова.
| Temperature | Эффект | Когда использовать |
|---|---|---|
| 0.0 - 0.3 | Детерминированный выбор самого вероятного токена. Текст сухой, фактологичный, повторяющийся. | Технические задания, извлечение фактов, кодогенерация, где важна точность. |
| 0.4 - 0.7 | "Золотая середина". Баланс между предсказуемостью и креативностью. Самый частый выбор. | Общие диалоги, написание статей, ответы на вопросы. |
| 0.8 - 1.2 | Высокая случайность. Текст может становиться бессвязным, но очень креативным. | Поэзия, генерация идей, творческое письмо. |
| > 1.2 | Экстремальная случайность. Часто приводит к бессмыслице. | Эксперименты, генерация абсурда. |
Temperature = 0 — это особый случай. При нулевой температуре модель всегда выбирает токен с самой высокой вероятностью, делая генерацию полностью детерминированной (при одинаковом seed). Это объясняет, почему ваша модель даёт один и тот же ответ.
# Сравнение temperature
response_low = llm("Опиши облако", seed=-1, temperature=0.2) # Сухо: "Облако - скопление водяного пара..."
response_mid = llm("Опиши облако", seed=-1, temperature=0.7) # Баланс: "Пушистое белое облако плыло..."
response_high = llm("Опиши облако", seed=-1, temperature=1.1) # Креатив: "Облако похоже на сахарную вату, которую забыл гигант..."3 Top_p (Nucleus Sampling): фокус на вероятных вариантах
Что это: Альтернатива или дополнение к temperature. Вместо рассмотрения всех возможных токенов, мы выбираем из наименьшего набора, совокупная вероятность которого превышает порог p.
Допустим, у нас есть токены с вероятностями: [0.5, 0.3, 0.1, 0.06, 0.04]. При top_p=0.9 мы возьмём первые два токена (0.5+0.3=0.8), но не дойдём до третьего, потому что 0.8+0.1=0.9, что уже достигает или превышает порог. Выбор будет делаться только из этих двух-трёх наиболее вероятных кандидатов.
- top_p = 0.9 - 1.0: Рассматривается широкий спектр вариантов, включая маловероятные. Больше разнообразия, но выше риск бессмыслицы.
- top_p = 0.5 - 0.8: Оптимальный диапазон для большинства задач. Ограничивает выбор наиболее вероятными путями, улучшая связность.
- top_p < 0.5: Жёсткое ограничение. Может слишком сузить выбор, особенно в сочетании с низкой temperature.
Важный нюанс: top_p и temperature взаимодействуют. Temperature изменяет исходное распределение вероятностей, а top_p затем отсекает его. Обычно используют что-то одно.
Ошибка новичка: Установка temperature=0.8 и top_p=0.1 одновременно. Temperature пытается "размазать" вероятности и добавить случайности, а top_p=0.1 тут же отсекает почти все варианты, оставляя, возможно, один-два токена. Результат непредсказуем и часто неоптимален.
Пошаговый план: от попугая к импровизатору
Вот как настроить вашу локальную LLM (на примере llama.cpp или обёрток), чтобы получать разнообразные и качественные ответы.
Шаг 1: Сбросьте seed
Первым делом убедитесь, что seed не зафиксирован. В llama-cpp-python это seed=-1. В командной строке llama.cpp проверьте флаг --seed или -s. Установите значение, указывающее на случайную инициализацию (часто -1 или 0, зависит от версии).
Шаг 2: Выберите стратегию — temperature ИЛИ top_p
Не мешайте всё вместе. Для начала выберите один метод управления случайностью.
- Для общего использования: Начните с
temperature=0.7иtop_p=1(отключён). Поэкспериментируйте, меняя только temperature. - Для более контролируемой креативности: Попробуйте
temperature=0.8иtop_p=0.9. - Для фактологической точности: Используйте
temperature=0.3иtop_p=0.5.
Шаг 3: Протестируйте и оцените
Не доверяйте абстрактным цифрам. Задайте один и тот же вопрос 5-10 раз с выбранными параметрами. Используйте промпты для тестирования, чтобы оценить не только разнообразие, но и качество ответов. Стала ли модель выдавать откровенную ерунду? Или, наоборот, слишком шаблонные фразы?
Шаг 4: Запомните связку для воспроизводимости
Когда найдёте оптимальные параметры для конкретной задачи (например, генерация кода или креативное письмо), запишите их вместе со значением seed, если нужна воспроизводимость. Например: Кодогенерация: seed=123, temperature=0.2, top_p=0.4.
# Пример запуска через llama.cpp CLI с параметрами для "креативного режима"
./main -m ./model.gguf -p "Напиши короткий детективный рассказ" --seed -1 --temp 0.85 --top-p 0.92 -n 256Частые ошибки и подводные камни
Даже зная теорию, можно наступить на грабли. Вот самые распространённые из них.
| Ошибка | Почему происходит | Как исправить |
|---|---|---|
| Ответы всё равно повторяются, хотя seed=-1 | Temperature установлена в 0 или очень близкое к нулю значение (например, 0.01). | Увеличьте temperature до 0.4 или выше. |
| Текст стал полной абракадаброй | Слишком высокие temperature (>1.0) и/или top_p (>0.95) одновременно. | Снизьте temperature до 0.8-0.9 и используйте top_p около 0.9. |
| Модель "зацикливается" на одной фразе | Низкое значение top_p (например, 0.1) в сочетании с определённым контекстом может ограничить выбор до одного повторяющегося токена. | Повысьте top_p до 0.7-0.8 или отключите его (значение 1). |
| Разные инструменты дают разное поведение при одинаковых параметрах | Ollama, LM Studio, llama-cpp-python могут по-разному интерпретировать значения или иметь разные значения по умолчанию для не указанных параметров. | Всегда явно указывайте ВСЕ параметры генерации (seed, temp, top_p, top_k, penalty). Сравнивайте не цифры, а поведение. |
Ещё одна ловушка — частотный штраф (frequency penalty) и штраф присутствия (presence penalty). Эти параметры, доступные в продвинутых обёртках, наказывают модель за повторение уже использованных токенов или тем. Их можно использовать для борьбы с зацикливанием, но они добавляют ещё один уровень сложности. Начинайте с основных параметров.
Практика: настройка под конкретные задачи
Теория — это хорошо, но давайте посмотрим на реальные пресеты.
- Кодогенерация (например, с помощью CodeLlama 13B): Нужна точность.
seed=любое (для воспроизводимости), temperature=0.1-0.3, top_p=0.4-0.6. Это минимизирует ошибки и генерирует предсказуемый, рабочий код. - Креативное письмо (например, Mistral 7B): Нужны вариации.
seed=-1, temperature=0.8-0.95, top_p=0.9-0.95. Будьте готовы к тому, что часть сгенерированного будет странной — это плата за креативность. - Анализ данных/Резюме текста: Баланс.
seed=-1, temperature=0.5-0.7, top_p=0.8. Это даст стабильные, но не абсолютно идентичные результаты. - Диалоговый агент (например, с Llama 3.1 8B): Естественность.
seed=-1, temperature=0.7-0.85, top_p=0.9. Помогает избежать роботизированных повторяющихся реплик.
Помните, что разные модели по-разному реагируют на одни и те же значения. То, что работает для Llama 3.2, может быть излишним для более старой модели. Всегда проводите калибровку на своей конкретной модели и задаче.
Что делать, если ничего не помогает?
Бывает и такое. Вы перепробовали все комбинации, а модель всё равно выдаёт шаблонные или повторяющиеся ответы. Вот куда стоит смотреть дальше:
- Проверьте системный промпт: Некоторые обёртки (как в Ollama) добавляют невидимый системный промпт, который может ограничивать креативность.
- Увеличьте контекст: Короткий контекст или его переполнение могут вынуждать модель идти по самому безопасному (читай — скучному) пути.
- Измените сам запрос: Иногда проблема не в параметрах, а в том, как сформулирован промпт. Добавьте прямые инструкции: "Будь креативным", "Придумай несколько вариантов", "Не используй шаблонные фразы".
- Посмотрите на саму модель: Сильно квантованные модели (например, q2_K) из-за потери информации могут иметь меньше "вариантов для выбора" в своих весах, что делает их более детерминированными. Попробуйте модель с более высоким битрейтом квантования (q6_K или q8).
И последний, неочевидный совет: иногда проблема — в вас. Мы, тестируя модели, задаём ей одни и те же скучные вопросы и ожидаем гениальных разных ответов. Попробуйте задавать по-настоящему открытые, сложные или провокационные вопросы. Модель может просто не "видеть" пространства для манёвра в вашем исходном промпте. Используйте промпты для сравнения LLM, чтобы оценить её возможности объективно.