SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-10

Как увеличить длину контекста num_ctx в Ollama

Ollama обрезает промпты из-за малого значения num_ctx по умолчанию. Узнайте, как задать размер окна контекста для запроса или сервера и рассчитать потребление RAM для KV-кэша.

Что делает num_ctx и почему ваш длинный промпт был обрезан

Длина контекста Ollama — это количество токенов, которое загруженная модель может одновременно удерживать в оперативной памяти, и num_ctx — это параметр, который задает данное значение. Ollama выбирает значение по умолчанию, которое значительно меньше максимального, заявленного для модели, поэтому длинный промпт обрезается еще до того, как модель успевает его прочитать. В ответе системы нет никаких уведомлений о том, что это произошло.

Для Llama 3.1 8B в библиотеке моделей Ollama указано окно контекста 128k. Стандартный сервер не предоставит вам такой объем. В документации самой Ollama на разных страницах приводятся разные значения по умолчанию: в FAQ указано 4096 токенов, в справочнике Modelfile сказано, что num_ctx по умолчанию равно 2048, а на странице о длине контекста говорится, что значение по умолчанию выбирается исходя из доступной VRAM (видеопамяти): 4k при объеме менее 24 GiB, 32k при объеме от 24 до 48 GiB и 256k при большем объеме. Каждое из этих утверждений было верно для определенных сборок. Это расхождение — полезный урок: проверяйте значение на своем работающем сервере, а не доверяйте любой странице, включая эту.

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

Проверка фактической длины контекста Ollama на сервере

Проверка, работающая на любой сборке — это prompt_eval_count, количество токенов запроса, которое, по отчету сервера, было обработано. Отправьте запрос, превышающий объем контекста, и это число остановится на пределе.

sudo apt update && sudo apt install -y jq
LONG=$(python3 -c "print('the quick brown fox jumps over the lazy dog. ' * 2000)")
jq -n --arg p "$LONG" '{model:"llama3.1:8b", prompt:$p, stream:false, options:{num_ctx:4096}}' |
  curl -s http://localhost:11434/api/generate -d @- |
  jq '{prompt_eval_count, prompt_eval_duration}'

Этот запрос содержит около 18,000 слов, что значительно больше 4096 токенов. Значение prompt_eval_count возвращается близким к 4096, а не к реальному количеству токенов, так как сервер отбросил остаток. Запустите его снова с "num_ctx":16384, и счетчик увеличится. Если ваша сборка возвращает ошибку вместо усечения, это тот же результат, но с более явным уведомлением.

ollama ps

Столбец CONTEXT в сборках, которые его выводят, содержит длину контекста, с которой загруженная модель работает в данный момент. Столбец PROCESSOR рядом с ним показывает, где размещена модель. 100% CPU — это нормальное состояние для VPS без GPU. Разделение вида 30%/70% CPU/GPU на сервере с GPU означает, что веса вместе с кэшем больше не помещаются в VRAM, и обычно это происходит из-за увеличенного num_ctx.

journalctl -u ollama --no-pager | grep -i n_ctx | tail -n 5

Исполнитель инференса выводит размер контекста в строке, содержащей n_ctx. Точная формулировка меняется от релиза к релизу, поэтому отсутствие строки следует считать переименованием, а не доказательством чего-либо.

Четыре способа задать num_ctx

В запросе. Отправьте "options": {"num_ctx": 16384} в /api/generate или /api/chat. Этот параметр имеет приоритет над всеми остальными и применяется только к данному вызову. Если значение отличается от того, с которым работает загруженная модель, сервер сначала перезагружает модель, что можно заметить по load_duration в ответе: время выполнения прыгает с почти нулевого до нескольких секунд.

В интерактивной сессии. Внутри ollama run введите /set parameter num_ctx 16384. Настройка действует в течение текущей сессии.

В Modelfile. Это «запекает» значение в именованную модель, поэтому каждый клиент получает его без изменений на своей стороне.

FROM llama3.1:8b
PARAMETER num_ctx 16384
ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16k

На сервере. OLLAMA_CONTEXT_LENGTH задает значение по умолчанию для каждого запроса, в котором не указан собственный num_ctx. При использовании systemd добавьте drop-in файл вместо редактирования основного файла юнита.

sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"
sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama ps

Приоритет настроек наиболее важен при отладке чужого клиента. Запрос, содержащий num_ctx, имеет приоритет над значением по умолчанию на сервере, поэтому чат-интерфейс или агент, отправляющий собственное небольшое значение, незаметно отменяет ваши изменения в systemd. Когда вы настраиваете агент для программирования на работу с вашим сервером Ollama, проверьте, что именно отправляет клиент, прежде чем винить сервер.

Почему нельзя просто установить num_ctx на максимум модели

Механизм внимания (attention) заставляет каждый токен «смотреть» на все предыдущие. Ключи и значения, вычисленные для ранних токенов, сохраняются, чтобы не пересчитывать их для каждого нового токена; это хранилище называется KV cache (кэш ключей и значений). Он выделяется для всего объема num_ctx при загрузке модели, а не по мере роста диалога, поэтому большой контекст потребляет память даже при запросе из одной строки.

Руководство DigitalOcean по стоимости инференса приводит расчеты в одну строку:

kv_bytes_per_token = 2 * layers * kv_heads * head_dim * bytes_per_value

Цифра 2 учитывает ключи и значения по отдельности. Остальные числа возьмите из характеристик вашей модели.

curl -s http://localhost:11434/api/show -d '{"model":"llama3.1:8b"}' |
  jq '.model_info | {ctx: ."llama.context_length", layers: ."llama.block_count", heads: ."llama.attention.head_count", kv_heads: ."llama.attention.head_count_kv", embed: ."llama.embedding_length"}'

Llama 3.1 8B имеет 32 слоя и 8 голов ключей/значений. Размерность головы — это embed, деленное на heads, то есть 4096 / 32 = 128; некоторые модели публикуют это значение напрямую как llama.attention.key_length. Кэш по умолчанию хранит значения f16, поэтому bytes_per_value равно 2, и расчет 2 32 8 128 2 дает 131 072 байта. Это 128 KiB кэша на каждый отдельный токен контекста. Умножьте это на длину контекста, и стоимость перестанет быть абстрактной.

ChartLlama 3.1 8B at f16: KV cache and total RAM by context length, in GiB
The data behind this chart
[
  {
    "label": "4k",
    "kv_cache_gib": 0.5,
    "total_ram_gib": 5.1
  },
  {
    "label": "8k",
    "kv_cache_gib": 1,
    "total_ram_gib": 5.6
  },
  {
    "label": "16k",
    "kv_cache_gib": 2,
    "total_ram_gib": 6.6
  },
  {
    "label": "32k",
    "kv_cache_gib": 4,
    "total_ram_gib": 8.6
  },
  {
    "label": "64k",
    "kv_cache_gib": 8,
    "total_ram_gib": 12.6
  },
  {
    "label": "128k",
    "kv_cache_gib": 16,
    "total_ram_gib": 20.6
  }
]

Эти строки 6 — результат арифметики по формуле выше, а не измерения. Итоговый столбец включает 4.9 GB загружаемых данных, которые библиотека Ollama указывала для llama3.1:8b в августе 2026 года (это 4.6 GiB), и не учитывает вычислительные буферы и сам процесс сервера. Рассматривайте это как минимально возможный порог.

Суть в масштабировании. При 8k кэш занимает 1 GiB, что является погрешностью по сравнению с весами модели. При полном контексте модели в 128k он занимает 16 GiB — более чем в три раза больше весов, что в сумме дает около 20.6 GiB. Таким образом, VPS с 4 GB памяти не сможет загрузить эту модель с полезным контекстом. VPS с 8 GB комфортно работает на 8k. VPS с 16 GB позволяет использовать 32k, оставляя место для остальных процессов системы. Каждый из этих порогов сдвигается вверх вместе с весами модели, поэтому, если вы сравниваете более крупную модель с этой 8B, те же расчеты, выполненные для тега Qwen 27B на VPS без GPU, показывают, как мало остается места для контекста при объеме оперативной памяти от 8 до 64 GB.

Что происходит, если KV cache не помещается в память

На VPS без GPU процесс просто увеличивает потребление памяти. Отслеживайте его во время загрузки модели и выполнения длинного запроса.

free -m
ps -eo rss,comm --sort=-rss | head -n 5

RSS (resident set size) отображается в килобайтах. Если значение используемого swap в free -m начинает расти, уменьшите размер контекста. KV cache, вытесненный в swap, приводит к тому, что генерация каждого токена занимает секунды, так как для каждого нового токена система считывает весь кэш целиком.

Если на сервере полностью заканчивается оперативная память, ядро выбирает самый ресурсоёмкий процесс и завершает его (OOM kill).

sudo dmesg | grep -i "killed process"

Строка с сообщением Out of memory: Killed process 1234 (ollama) означает, что запрошенный контекст не поместился в память. Ollama часто отклоняет запрос до того, как это произойдет, и запрос завершается с ошибкой, в которой указан объем требуемой памяти в сравнении с объемом свободной.

На сервере с GPU сбой происходит менее заметно. Слои модели вытесняются в системную RAM, ollama ps показывает распределение нагрузки между CPU и GPU, а пропускная способность резко падает. Степень падения зависит от вашего оборудования, поэтому измеряйте количество токенов в секунду на своей системе для каждого значения контекста, а не полагайтесь на показатели с чужих машин.

Время префилла растет быстрее, чем длина промпта

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

Ответ содержит результаты измерений, поэтому вам не нужно полагаться на предположения.

jq -n --arg p "$LONG" '{model:"llama3.1:8b", prompt:$p, stream:false, options:{num_ctx:16384}}' |
  curl -s http://localhost:11434/api/generate -d @- |
  jq '{tokens: .prompt_eval_count, prefill_seconds: (.prompt_eval_duration/1000000000)}'

Запустите этот тест с коротким промптом, а затем с длинным, после чего разделите количество токенов на количество секунд в каждом случае. На VPS без GPU префилл обычно является самой медленной частью запроса с длинным контекстом, и показатель токенов в секунду, полученный на коротком промпте, не позволит его спрогнозировать.

Больше всего это сказывается при высокой конкурентности. Каждый обрабатываемый запрос требует собственного кэша, поэтому память на графике выше указана для одного запроса, а не для всего сервера. Один длинный запрос может занять все ресурсы, пока короткие запросы выстраиваются в очередь. Устанавливайте OLLAMA_NUM_PARALLEL осознанно и ознакомьтесь с материалом сколько одновременных пользователей может обслужить одна self-hosted LLM, прежде чем увеличивать оба этих параметра одновременно.

Возврат контекста за счет уменьшения кэша

bytes_per_value в формуле — это параметр, который вы контролируете. В FAQ Ollama описан OLLAMA_KV_CACHE_TYPE, где f16 является значением по умолчанию (2 байта), плюс q8_0 (1 байт) и q4_0 для меньших значений. Переход на q8_0 сокращает кэш вдвое, поэтому строка 32k занимает 2 GiB вместо 4 GiB. В том же FAQ описан OLLAMA_FLASH_ATTENTION=1, который требуется некоторым сборкам для активации квантованного кэша.

[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"

Проверяйте факты, а не стройте предположения: перезапустите сервис, загрузите модель с тем же num_ctx, что и раньше, и сравните RSS. Поддержка зависит от модели и бэкенда, поэтому если настройка не дает эффекта, значит, ваша комбинация ее не поддерживает. В документации эти опции перечислены без гарантии качества результата, поэтому протестируйте q4_0 на своих промптах, прежде чем полагаться на них. Если вы здесь именно из-за этих параметров, Ollama и llama.cpp предоставляют к ним разный доступ.

Рецепт выбора значения num_ctx

  1. Узнайте максимальный контекст модели, количество слоев и количество ключей/значений (KV heads) из /api/show.
  2. Рассчитайте количество байт на токен по формуле, затем умножьте на желаемый размер контекста.
  3. Прибавьте размер весов модели, сравните результат со свободной оперативной памятью и оставьте не менее 1 GiB для работы остальной системы.
  4. Установите значение, загрузите модель и подтвердите примененные параметры с помощью ollama ps и prompt_eval_count.
  5. Запустите реальную рабочую нагрузку, наблюдая за free -m, и уменьшите контекст вдвое, если начинает использоваться swap.

Большинству задач требуется меньше контекста, чем обычно выделяют пользователи. Для суммаризации длинного отчета достаточно 16k. Интерфейс поиска, который вставляет пять фрагментов документов, редко превышает 8k. Агент для написания кода, который считывает целые файлы, — это тот случай, когда действительно нужно 64k или более; в такой ситуации следует подбирать конфигурацию сервера под размер контекста, а не наоборот. Если сервер еще не настроен, начните с рабочей установки Ollama на VPS и настраивайте контекст после того, как модели начнут корректно загружаться.

FAQ

Какова длина контекста по умолчанию в Ollama?

Она зависит от сборки и оборудования, поэтому проверяйте значение, а не полагайтесь на предположения. В FAQ Ollama указано 4096 токенов, в справочнике Modelfile задокументировано значение по умолчанию num_ctx, равное 2048, а на странице о длине контекста указано, что значение по умолчанию выбирается исходя из доступной VRAM: 4k при объеме менее 24 GiB, 32k при объеме от 24 до 48 GiB и 256k при большем объеме. VPS, работающий только на CPU, попадает в категорию с минимальным значением. ollama ps выводит примененный контекст в сборках, где есть этот столбец, а prompt_eval_count в ответе API подтверждает его для любой сборки.

Почему Ollama игнорирует начало моего длинного промпта?

Потому что промпт оказался длиннее окна контекста, поэтому сервер обрезал его до того, как модель успела его обработать, при этом ошибка не была возвращена. Отправьте тот же промпт еще раз с большим значением num_ctx и следите за тем, как растет prompt_eval_count в ответе. Если это число не меняется, значит, что-то между вами и сервером самостоятельно устанавливает num_ctx, что часто встречается в чат-интерфейсах и агентских фреймворках.

Сколько дополнительной оперативной памяти требуется для большего num_ctx?

Умножьте длину контекста на стоимость кэша в расчете на один токен, которая составляет 2 * layers * kv_heads * head_dim * bytes_per_value. Для Llama 3.1 8B в формате f16 это 128 KiB на токен, поэтому 32k токенов потребуют 4 GiB, а полные 128k — 16 GiB сверх весов модели. Кэш выделяется при загрузке модели, поэтому большой num_ctx занимает этот объем памяти, даже если ваши промпты остаются короткими.

Делает ли большее окно контекста Ollama медленнее?

Да, по двум причинам. Время префилла (prefill) растет пропорционально квадрату длины промпта, поэтому длинный ввод задерживает появление первого токена на время, превышающее простое увеличение длины. Увеличенный кэш также конкурирует за память: на GPU-сервере это вытесняет слои в системную RAM, а на CPU-сервере приближает систему к использованию swap. Большой num_ctx, который вы никогда не заполняете, все равно занимает память, хотя и не увеличивает время префилла.

Можно ли установить num_ctx постоянно для одной модели?

Да. Создайте Modelfile, содержащий FROM llama3.1:8b и PARAMETER num_ctx 16384, а затем выполните ollama create llama3.1-16k -f ./Modelfile. Каждый клиент, запрашивающий llama3.1-16k, получит этот контекст без необходимости отправки дополнительных параметров. Запрос, содержащий собственный num_ctx, все равно будет иметь приоритет, поэтому данный метод задает значение по умолчанию, а не жесткий лимит.