Как ограничить длину ответа в Ollama через num_predict
Узнайте, как правильно использовать параметр num_predict для лимита токенов. Разберем иерархию настроек, приоритеты конфигураций и обработку статуса done_reason при остановке.
Что делает параметр num_predict в Ollama
num_predict — это опция Ollama, которая ограничивает количество токенов, генерируемых моделью в одном ответе. Учитываются только выходные токены, поэтому размер промпта не влияет на этот лимит. Когда модель достигает установленного предела, генерация останавливается, иногда на середине слова, а ответ возвращается с параметром done_reason, установленным в length.
Это вся функциональность данной опции. Сложность заключается в том, что Ollama предоставляет три различных места для установки этого значения, и приоритет имеет настройка, расположенная ближе всего к запросу. Почти каждый отчет о том, что «num_predict не работает», связан с тем, что один уровень настроек незаметно переопределяет другой.
num_predict — это не num_ctx
Эти два параметра путают чаще, чем любые другие настройки в Ollama, и эта путаница приводит к потере времени при отладке.
num_ctx определяет, какой объем данных модель может прочитать. Это размер контекстного окна, которое содержит промпт и всё, что было сгенерировано к текущему моменту. Увеличение этого значения требует больше памяти, так как кэш ключей и значений (key/value cache), который модель хранит для этих токенов, растёт вместе с размером окна. Расчет num_ctx для вашего оборудования — это отдельная задача со своими специфическими ошибками.
num_predict определяет, какой объем данных модель может записать. Это правило остановки генерации, а не параметр выделения ресурсов. Увеличение этого значения влияет на время выполнения, а не на объем оперативной памяти, и никакие ресурсы заранее не резервируются.
Эти параметры пересекаются в одном аспекте. Сгенерированные токены попадают в контекстное окно по мере их создания, поэтому генерация ответа может остановиться из-за заполнения окна, а не из-за достижения установленного вами лимита. Ollama сообщает length в обоих случаях, поэтому число, позволяющее их различить, — это eval_count, которое подробно рассматривается ниже.
Установка значения через Modelfile
Modelfile позволяет «запечь» значение непосредственно в создаваемую модель. Создайте файл:
FROM qwen3:8b
PARAMETER num_ctx 8192
PARAMETER num_predict 512Затем выполните сборку и проверьте результат:
ollama create qwen3-capped -f Modelfile
ollama show --parameters qwen3-cappedollama show --parameters выводит по одной строке на каждый сохраненный параметр с его значением. Если в выводе отсутствует num_predict, значит, в модели нет жестко заданного ограничения, и применяются стандартные настройки Ollama. ollama show --modelfile qwen3-capped выводит полное определение модели; это самый быстрый способ скопировать параметры, с которыми поставляется существующая модель. Создание модели с ограничением таким способом практически не требует дополнительного места на диске, так как новая запись повторно использует уже загруженные веса базовой модели, а не копирует их. Стоит знать, где Ollama хранит эти файлы, прежде чем корневой раздел VPS будет переполнен.
Это подходящий уровень для значений, которые должны наследоваться всеми вызывающими сторонами. Этот способ не подходит, если вы ожидаете, что значение будет окончательным, так как это не так.
Установка параметра в объекте options для каждого запроса
Каждый эндпоинт генерации принимает объект options, внутри которого размещается num_predict:
curl http://localhost:11434/api/generate -d '{
"model": "qwen3:8b",
"prompt": "Explain what a reverse proxy does.",
"stream": false,
"options": { "num_predict": 128 }
}'/api/chat использует тот же ключ options с тем же значением. Указанное здесь значение применяется только к данному вызову и ни к чему больше. Это уровень, на котором работают ваши инструменты: чат-интерфейс, скрипт, обёртка SDK или агент для написания кода. Все они отправляют объект options, независимо от того, отображают ли они соответствующее поле в интерфейсе.
Установка параметров для одного сеанса с помощью /set
Внутри ollama run интерактивный сеанс задает параметры для всех последующих действий в рамках этого сеанса:
>>> /set parameter num_predict 256
>>> /show parameters/show parameters выводит данные, которые сеанс отправит со следующим сообщением; это самый быстрый способ убедиться, что изменения вступили в силу. Значение сохраняется до тех пор, пока вы не введете /bye. Чтобы сохранить настройки, /save qwen3-capped записывает текущий сеанс, включая параметры, как новую модель. Все, что вы /set здесь, не передается другим клиентам.
Какой параметр имеет приоритет и почему ваш игнорируется
Порядок приоритетов прост. Параметры, переданные в запросе, имеют преимущество перед всеми остальными. Строка PARAMETER num_predict в файле Modelfile модели является резервным значением, которое используется, если в запросе параметр не указан. Если ни то, ни другое не задано, применяются встроенные значения по умолчанию Ollama.
/set parameter не является третьим правилом. Интерактивная сессия выступает в роли API-клиента, поэтому всё, что вы там задаёте, отправляется как options этого запроса, что и объясняет, почему это переопределяет Modelfile для данной сессии.
Теперь о сбое, который это объясняет. Вы добавляете PARAMETER num_predict 512, пересобираете модель, но ответы всё равно достигают тысяч токенов. Ваш параметр присутствует, и ollama show --parameters это подтверждает. Однако он переопределяется при каждом запросе, так как клиент отправляет собственный объект options с собственным числом — часто это число, которое вы ввели в настройках несколько месяцев назад и забыли. ollama show считывает сохранённую модель. Он не может показать вам то, что приходит по HTTP.
Проверьте серверную часть одной командой. Отправьте запрос, который должен сгенерировать длинный ответ, принудительно установите низкий лимит и считайте два поля:
curl -s http://localhost:11434/api/generate -d '{
"model": "qwen3-capped",
"prompt": "Describe the Linux boot process in detail.",
"stream": false,
"options": { "num_predict": 32 }
}' | jq '.done_reason, .eval_count'Эта команда должна вывести "length" и 32. Если утилита jq отсутствует, установите её с помощью sudo apt install -y jq. Ответ "length" и 32 означает, что сервер учитывает параметр, а ваше приложение отправляет что-то другое. Чтобы увидеть, как сервер интерпретирует запрос, перезапустите его с переменной OLLAMA_DEBUG=1 в окружении и следите за journalctl -u ollama -f во время взаимодействия с вашим приложением.
Отрицательные значения и числа, которые не следует копировать
num_predict также принимает отрицательные значения, которые являются не счетчиками, а служебными метками. Одно отрицательное значение означает «не ограничивать, продолжать генерацию». Другое использовалось для обозначения «заполнить оставшийся контекст». По состоянию на август 2026 года в справочнике Ollama Modelfile значением по умолчанию указано -1, что означает бесконечную генерацию, а в более ранних версиях той же таблицы для заполнения контекста указывалось -2.
Считайте, что всё это зависит от версии, так как данные менялись. В документации значение 128 долгое время указывалось как стандартное, прежде чем запись была исправлена в конце 2024 года, поэтому многие руководства до сих пор повторяют старое число. Изучите справочник параметров Modelfile для той версии, которую вы используете, а затем подтвердите поведение с помощью проверки eval_count, описанной выше. Значение, которое вы проверили на собственном сервере, важнее любого значения, прочитанного где-либо еще, включая эту статью.
Почему длина вывода — основной фактор затрат на VPS без GPU
Генерация состоит из двух фаз, которые выполняются с разной скоростью. Токены промпта обрабатываются пакетами, по много штук за раз. Токены вывода создаются по одному, и каждый из них требует полного прохода по весам модели. На VPS без GPU этот проход ограничен пропускной способностью памяти, поэтому один сгенерированный токен стоит значительно дороже, чем один токен промпта. Поскольку для каждого прохода необходимо считать все веса, количество байт, занимаемое каждым весом, определяет предел скорости генерации токенов. Именно поэтому сборка в формате q4 декодирует быстрее, чем та же модель в q8 или fp16.
Запросите ответ без потоковой передачи, и вы увидите цифры:
"prompt_eval_count": 26,
"prompt_eval_duration": 107345000,
"eval_count": 237,
"eval_duration": 4289432000Длительность указана в наносекундах. В этом блоке, который является примером ответа из документации Ollama API, а не замером конкретного сервера, 26 токенов промпта заняли около 0.1 секунды, тогда как 237 токенов вывода — около 4.3 секунд. Ваша собственная скорость генерации — это eval_count, делённое на eval_duration, переведённое в секунды, и измерение количества токенов в секунду на вашем оборудовании стоит выполнить до того, как вы начнёте что-либо настраивать. Эта скорость зависит от модели так же сильно, как и от машины, поэтому, если длинные ответы создают основную нагрузку, модель, оптимизированная для быстрого декодирования, такая как Nemotron 3.5 Lightning на VPS, позволит сэкономить время, которое в противном случае ограничивается лимитом.
Арифметика проста. При скорости 8 токенов в секунду ответ на 2,000 токенов занимает ресурсы машины более чем на четыре минуты, при этом модель не знает, что вам нужен был всего лишь абзац. Модель с функцией рассуждения тратит часть этого бюджета на «размышления» перед тем, как написать первое слово, а эти размышления генерируются по одному токену за раз, как и всё остальное. Поэтому уровень рассуждений, который вы запрашиваете — это ещё один рычаг управления теми же затратами. Некоторые модели также могут зацикливаться, повторяя фразу, пока их что-то не остановит. Без ограничения этот единственный запрос будет занимать ядро процессора до тех пор, пока не закончится контекстное окно. num_predict — это настройка, которая ограничивает данный процесс, что критически важно на небольшом самостоятельно размещённом VPS с Ollama, где один длинный запрос может занять все ресурсы машины.
Усеченный вывод обычно вызван ограничением, а не ошибкой модели
Симптомы часто выглядят как сбой модели. Ответ обрывается на полуслове. JSON не парсится, так как отсутствует закрывающая фигурная скобка. Первая реакция — винить модель или квантование. Сначала изучите ответ.
done_reason отвечает на вопрос напрямую. stop означает, что модель завершила работу самостоятельно, выдав токен конца последовательности или совпав с одной из строк в опции stop. length означает, что генерация была прервана из-за нехватки места. Когда вы видите length, сравните eval_count с вашим ограничением: точное совпадение означает, что его остановил num_predict, а меньшее число указывает на то, что сначала заполнилось контекстное окно.
При потоковой передаче эти поля приходят в финальном фрагменте, который содержит "done": true. Многие клиентские библиотеки отбрасывают этот фрагмент и передают вашему коду только текст, поэтому одно и то же усечение выглядит необъяснимым внутри приложения, но очевидным при использовании curl. Если библиотека скрывает это, отправьте один запрос с curl, чтобы узнать, что на самом деле ответил сервер.
Еще один момент поможет сэкономить время. Увеличение num_predict не заставляет модель писать больше. Оно лишь убирает потолок. Если ответ заканчивается на 200 токенах при done_reason из stop, значит, модель решила, что закончила, и увеличение лимита ничего не изменит. Короткие ответы с stop — это проблема промпта. Короткие ответы с length — это проблема ограничения.
Выбор значения
- Для интерактивного чата оставьте значение без ограничений и используйте Ctrl+C, чтобы остановить бесконечный ответ. Вы в любом случае следите за экраном.
- Для любых скриптов установите ограничение. Генерация без лимита внутри цикла — это причина, по которой пакетное задание, рассчитанное на десять минут, может продолжать выполняться на следующее утро.
- Для структурированного вывода установите лимит выше размера самого большого документа, который вы ожидаете. В случае
done_reasonизlengthсчитайте это критической ошибкой и повторите запрос, вместо того чтобы пытаться обработать полученный результат. - Для агента написания кода значение должно находиться в конфигурации самого агента, так как агент передает свои параметры с каждым запросом. В Настройка агента для работы с Ollama описано, где хранятся эти параметры.
Лимит учитывает токены, а не слова или символы, поэтому не пытайтесь оценивать его «на глаз». Сгенерируйте один типичный ответ без ограничений, посмотрите на eval_count и установите лимит с запасом выше этого значения. Разные семейства моделей используют разные методы токенизации, поэтому значение, подходящее для модели Llama, может привести к обрезанию того же ответа при использовании модели Qwen 3 на том же VPS.
FAQ
В чем разница между num_ctx и num_predict в Ollama?
num_ctx — это размер контекстного окна, который определяет, какой объем данных может прочитать модель: ваш запрос плюс всё, что было сгенерировано ранее. Это расходует память, так как кэш ключей и значений (key/value cache) растет вместе с ним. num_predict задает количество токенов, которое модель может записать в одном ответе. Это расходует время, а не память, и заранее никакие ресурсы не резервируются. Сгенерированные токены учитываются в обоих параметрах, поэтому ответ может быть прерван любым из них.
Почему мой параметр num_predict игнорируется?
Потому что значение, переданное в запросе, имеет приоритет над значением, сохраненным в модели. Если вы укажете PARAMETER num_predict 512 в Modelfile, а затем будете использовать эту модель через чат-интерфейс или агент для программирования, клиент отправит собственный объект options, значение которого будет решающим. ollama show --parameters по-прежнему будет отображать ваше значение, так как команда считывает параметры сохраненной модели и не видит того, что приходит по HTTP. Отправьте один запрос с curl через "options": {"num_predict": 32} и убедитесь, что в ответе eval_count возвращается 32. Это подтвердит, что сервер работает корректно, и перенесет поиск проблемы в ваше приложение.
Как узнать, был ли вывод обрезан из-за num_predict?
Отправьте запрос с "stream": false и прочитайте done_reason. Значение stop означает, что модель завершила работу самостоятельно. Значение length означает, что место закончилось. Затем сравните eval_count с вашим ограничением: если они в точности совпадают, значит, генерацию остановил num_predict, а если eval_count меньше, значит, сначала заполнилось контекстное окно. При потоковой передаче оба поля приходят в последнем фрагменте с "done": true, который многие клиентские библиотеки отбрасывают до того, как ваш код успеет их увидеть.
Каково значение по умолчанию для num_predict?
Узнавайте его из своей собственной установки, а не из статей. По состоянию на август 2026 года в справочнике по Modelfile для Ollama значение по умолчанию указано как -1, что означает отсутствие ограничения на генерацию. Эта запись была исправлена в конце 2024 года после того, как в документации годами значилось 128. Отрицательные значения являются служебными метками, а не счетчиками, и в старых версиях той же таблицы также указывалось -2 для заполнения оставшегося контекста. Проверьте справочник параметров Modelfile для вашей версии, а затем подтвердите значение с помощью ollama show --parameters и одного запроса curl.
Увеличит ли повышение num_predict длину ответов модели?
Нет. Это лишь снимает верхний предел. Если ответ заканчивается на done_reason из stop, значит, модель решила, что закончила работу, и увеличение лимита ничего не изменит. В этом случае длина зависит от промпта: запрашивайте определенную структуру, количество разделов или заданный уровень детализации. Увеличивайте num_predict только тогда, когда done_reason возвращается как length.