Ollama: як налаштувати довжину контексту num_ctx
Ollama обрізає довгі prompt через мале вікно контексту. Дізнайтеся, як задати num_ctx для запиту або сервера та розрахувати RAM для KV cache.
Що робить num_ctx і чому довгий prompt було обрізано
Довжина контексту Ollama — це кількість токенів, які завантажена модель може одночасно зберігати в пам’яті, а num_ctx — параметр, який її визначає. Ollama вибирає значення за замовчуванням, значно менше за максимальне значення, заявлене для моделі, тому довгий prompt обрізається ще до того, як модель його прочитає. У відповіді немає жодної ознаки, що це сталося.
Для Llama 3.1 8B у бібліотеці моделей Ollama указано контекстне вікно 128k. Стандартний сервер не надасть вам такий обсяг. У власній документації Ollama на різних сторінках наведено різні значення за замовчуванням: у FAQ указано 4096 токенів, у довідці Modelfile зазначено, що num_ctx за замовчуванням має значення 2048, а на сторінці про довжину контексту сказано, що значення за замовчуванням вибирається на основі доступної VRAM (відеопам’яті): 4k для обсягу менше ніж 24 GiB, 32k для 24–48 GiB і 256k для обсягу понад 48 GiB. Кожне з цих значень було актуальним для певної збірки. Практичний висновок із цієї невідповідності: перевіряйте значення на власному запущеному сервері, а не покладайтеся на будь-яку сторінку, зокрема й на цю.
Обрізання відбувається непомітно, оскільки модель усе одно відповідає, і відповідь може залишатися переконливою. Вона була сформована на основі кінцевої частини вашого введення. Резюме, у якому пропущено першу половину документа, схоже на результат слабкої моделі. Зазвичай причина — замале контекстне вікно.
Перевірте фактичну довжину контексту 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 16384ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16kНа сервері. OLLAMA_CONTEXT_LENGTH задає значення за замовчуванням для кожного запиту, який не містить власного num_ctx. У systemd додайте drop-in-конфігурацію замість редагування unit-файла.
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama psПріоритет налаштувань особливо важливий під час налагодження клієнта, яким керує інша команда. Запит із num_ctx має вищий пріоритет за налаштування сервера, тому chat front end або агент, який надсилає власне мале значення, непомітно скасовує зміни в systemd. Коли ви підключаєте coding agent до сервера Ollama, перевірте, що надсилає клієнт, перш ніж звинувачувати сервер.
Чому не можна просто задати num_ctx на максимальне значення моделі
Механізм attention змушує кожен токен звертатися до всіх попередніх токенів. Обчислені для попередніх токенів keys і values зберігаються, щоб не обчислювати їх заново для кожного нового токена. Це сховище називається KV cache (key/value cache). Воно виділяється для всього значення num_ctx під час завантаження моделі, а не в міру зростання діалогу. Тому великий контекст споживає цю пам’ять навіть для однорядкового запиту.
У посібнику DigitalOcean про вартість inference наведено формулу в одному рядку:
kv_bytes_per_token = 2 * layers * kv_heads * head_dim * bytes_per_valueЧисло 2 означає, що keys і values рахуються окремо. Інші значення візьміть із власної моделі.
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 layers і 8 key/value heads. Розмір head дорівнює embed, поділеному на heads, тому тут 4096 / 32 = 128. Деякі моделі публікують це значення безпосередньо як llama.attention.key_length. Кеш за замовчуванням зберігає значення у форматі f16, тому bytes_per_value дорівнює 2. Відповідно, 2 32 8 128 2 = 131,072 bytes. Це 128 KiB кешу для кожного токена контексту. Помножте це значення на довжину контексту, і витрати пам’яті стануть очевидними.
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 рядків обчислено за наведеною вище формулою, а не виміряно. У стовпці total враховано завантаження обсягом 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 лише з CPU показують, як мало пам’яті залишається для контексту на системах із 8–64 GB.
Що відбувається, коли KV cache не вміщується
На VPS лише з CPU процес просто збільшується. Спостерігайте за ним під час завантаження моделі та виконання тривалого запиту.
free -m
ps -eo rss,comm --sort=-rss | head -n 5RSS (resident set size) виводиться в кілобайтах. Якщо використання swap у free -m починає зростати, зменште контекст. KV cache, розміщений у swap, спричиняє зупинки генерації на кілька секунд для кожного токена, оскільки кожен новий токен читає весь кеш.
Якщо пам’ять на сервері повністю закінчиться, ядро вибере найбільший процес і завершить його.
sudo dmesg | grep -i "killed process"Рядок із Out of memory: Killed process 1234 (ollama) означає, що вказаний вами контекст не вмістився. Ollama часто відмовляє ще до цього етапу, після чого запит завершується помилкою, де вказано потрібний обсяг пам’яті та доступний обсяг.
На сервері з GPU помилка менш очевидна. Частина шарів переміщується до системної RAM, ollama ps показує розподіл між CPU і GPU, а пропускна здатність різко падає. Наскільки саме вона впаде, залежить від вашого обладнання, тому вимірюйте кількість токенів за секунду на власному сервері для кожного значення контексту, а не покладайтеся на показник з іншої машини.
Час prefill зростає швидше, ніж довжина prompt
Prefill — це обробка вхідних даних до появи першого токена відповіді. Кожен токен prompt аналізує всі токени перед ним, тому загальний обсяг роботи зростає пропорційно квадрату довжини вхідних даних. Якщо подвоїти prompt, очікування першого токена зросте більш ніж удвічі.
Відповідь містить результат вимірювання, тому вам не потрібно покладатися на це твердження без перевірки.
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)}'Виконайте цю команду з коротким prompt, а потім із довгим, і в кожному випадку поділіть кількість токенів на кількість секунд. На VPS лише з CPU prefill зазвичай є найповільнішою частиною запиту з довгим контекстом, тому показник токенів за секунду, отриманий для короткого prompt, не дасть змоги спрогнозувати його продуктивність.
Найбільше це впливає на паралельну обробку запитів. Кожен запит, який обробляється, потребує власного кешу, тому обсяг пам’яті на наведеній вище діаграмі вказано для одного запиту, а не для всього сервера. Один довгий запит може зайняти весь сервер, через що короткі запити чекатимуть у черзі. Встановлюйте OLLAMA_NUM_PARALLEL свідомо та ознайомтеся з матеріалом про кількість одночасних користувачів, яких може обслуговувати self-hosted LLM, перш ніж одночасно збільшувати обидва значення.
Поверніть доступний контекст завдяки меншому кешу
bytes_per_value у формулі — це параметр, яким ви керуєте. У FAQ Ollama описано OLLAMA_KV_CACHE_TYPE, де значенням за замовчуванням є f16 — 2 bytes, а також q8_0 — 1 byte, і 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
- Візьміть максимальний контекст моделі, кількість її шарів і кількість голів key/value з
/api/show. - Обчисліть кількість байтів на токен за формулою, а потім помножте її на потрібний розмір контексту.
- Додайте розмір ваг, порівняйте результат із вільною RAM і залиште щонайменше 1 GiB для інших процесів сервера.
- Установіть значення, завантажте модель, а потім перевірте застосовані параметри за допомогою
ollama psіprompt_eval_count. - Запустіть реальне робоче навантаження, стежачи за
free -m, і зменште контекст удвічі, якщо почнеться використання swap.
Для більшості завдань потрібно менше контексту, ніж зазвичай задають. Для узагальнення довгого звіту достатньо 16k. Система retrieval, яка додає п’ять фрагментів документів, рідко передає більше 8k. Агент для роботи з кодом, який читає файли повністю, є випадком, коли справді потрібно 64k або більше. У такому разі конфігурацію сервера слід визначати за розміром контексту, а не навпаки. Якщо сервер ще не налаштований, почніть із працюючої інсталяції Ollama на VPS і налаштуйте контекст після того, як моделі почнуть стабільно завантажуватися.
FAQ
Яка довжина контексту є стандартною в Ollama?
Це залежить від збірки та апаратного забезпечення, тому перевіряйте значення, а не робіть припущення. У FAQ для Ollama зазначено 4096 токенів, у довідці щодо Modelfile — стандартне значення num_ctx, що дорівнює 2048, а на сторінці про довжину контексту описано стандартне значення, вибране за доступним VRAM: 4k для обсягу менше 24 GiB, 32k для 24–48 GiB і 256k для обсягу понад 48 GiB. VPS лише з CPU використовує нижню межу. ollama ps виводить застосовану довжину контексту в збірках, де є відповідний стовпець, а prompt_eval_count у відповіді API підтверджує її в кожній збірці.
Чому Ollama ігнорує початок мого довгого промпту?
Тому що промпт був довшим за вікно контексту. Сервер обрізав його до того, як модель отримала запит, і не повернув помилку. Надішліть той самий промпт ще раз із більшим num_ctx і простежте, як у відповіді змінюється prompt_eval_count. Якщо це число не збільшується, щось між клієнтом і сервером самостійно встановлює num_ctx. Це поширено для chat front end і агентських фреймворків.
Скільки додаткової RAM потребує більший 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, який ви ніколи не заповнюєте, усе одно споживає пам’ять, хоча й не збільшує час prefill.
Чи можна назавжди встановити num_ctx для однієї моделі?
Так. Створіть Modelfile, який містить FROM llama3.1:8b і PARAMETER num_ctx 16384, а потім виконайте ollama create llama3.1-16k -f ./Modelfile. Кожен клієнт, який запитує llama3.1-16k, отримуватиме цей контекст без передавання будь-яких options. Запит із власним num_ctx має вищий пріоритет, тому це встановлює стандартне значення, а не верхню межу.