Ollama: jak zwiększyć limit kontekstu num_ctx
Domyślny limit num_ctx w Ollama często powoduje ucinanie długich promptów bez ostrzeżenia. Dowiedz się, jak poprawnie skonfigurować parametr w Modelfile i oszacować zużycie VRAM.
Czym jest num_ctx i dlaczego długi prompt został ucięty
Długość kontekstu w Ollama to liczba tokenów, które załadowany model może jednocześnie przechowywać w pamięci, a num_ctx jest opcją, która ją definiuje. Ollama wybiera wartość domyślną znacznie niższą od maksymalnej deklarowanej przez model, dlatego zbyt długi prompt zostaje ucięty, zanim model zdąży go odczytać. Żaden element odpowiedzi nie informuje o wystąpieniu tego zdarzenia.
Model Llama 3.1 8B jest wymieniony w bibliotece modeli Ollama z oknem kontekstowym 128k. Standardowa konfiguracja serwera nie zapewni takiej wartości. Dokumentacja Ollama podaje różne wartości domyślne w różnych miejscach: FAQ wskazuje na 4096 tokenów, dokumentacja Modelfile podaje, że num_ctx domyślnie wynosi 2048, a strona o długości kontekstu informuje, że wartość domyślna jest dobierana na podstawie dostępnej pamięci VRAM (4k poniżej 24 GiB, 32k dla zakresu 24–48 GiB oraz 256k powyżej tej wartości). Każde z tych stwierdzeń było prawdziwe dla określonej wersji kompilacji. Ta rozbieżność stanowi istotną lekcję: należy odczytać wartość z własnego, uruchomionego serwera, zamiast polegać na jakiejkolwiek stronie, w tym na niniejszej.
Obcinanie danych przebiega w sposób niezauważalny, ponieważ model nadal generuje odpowiedź, która brzmi poprawnie. Została ona utworzona na podstawie końcowej części danych wejściowych. Podsumowanie, które pomija pierwszą połowę dokumentu, sprawia wrażenie słabego modelu. Zazwyczaj przyczyną jest zbyt małe okno kontekstowe.
Weryfikacja długości kontekstu Ollama faktycznie zastosowanej przez serwer
Weryfikacja działająca w każdej kompilacji to prompt_eval_count, czyli liczba tokenów promptu, którą serwer raportuje jako przetworzoną. Należy wysłać więcej danych, niż mieści kontekst, a liczba ta zatrzyma się na limicie.
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}'Ten prompt zawiera około 18 000 słów, czyli znacznie więcej niż 4096 tokenów. Wartość prompt_eval_count będzie bliska 4096, a nie rzeczywistej liczbie tokenów, ponieważ serwer odrzucił resztę. Należy uruchomić to ponownie z "num_ctx":16384, a liczba wzrośnie. Jeśli kompilacja zwraca błąd zamiast ucinania danych, oznacza to ten sam wynik, ale z wyraźniejszym komunikatem.
ollama psKolumna CONTEXT, w kompilacjach które ją wyświetlają, zawiera długość kontekstu, z jaką aktualnie działa załadowany model. Kolumna PROCESSOR obok niej pokazuje, gdzie znajduje się model. Wartość 100% CPU jest normalna na serwerze VPS bez GPU. Podział taki jak 30%/70% CPU/GPU na maszynie z GPU oznacza, że wagi wraz z pamięcią podręczną nie mieszczą się już w VRAM, a częstą przyczyną jest zwiększona wartość num_ctx.
journalctl -u ollama --no-pager | grep -i n_ctx | tail -n 5Moduł wykonawczy wnioskowania (inference runner) wypisuje rozmiar kontekstu w linii zawierającej n_ctx. Dokładne brzmienie komunikatu zmienia się między wydaniami, więc brak tej linii należy traktować jako zmianę nazewnictwa, a nie jako dowód czegokolwiek.
Cztery miejsca konfiguracji num_ctx
W żądaniu. Wyślij "options": {"num_ctx": 16384} do /api/generate lub /api/chat. Ta wartość ma najwyższy priorytet i dotyczy tylko pojedynczego wywołania. Jeśli wartość różni się od tej, z którą uruchomiono załadowany model, serwer najpierw przeładuje model, co można zaobserwować w load_duration w odpowiedzi: czas wzrasta z wartości bliskich zeru do pełnych sekund. To samo opóźnienie występuje, gdy model pozostawał bezczynny wystarczająco długo, aby zostać usuniętym z pamięci, dlatego po ustaleniu rozmiaru kontekstu warto utrzymać model w pamięci za pomocą keep_alive.
W sesji interaktywnej. Wewnątrz ollama run wpisz /set parameter num_ctx 16384. Ustawienie obowiązuje przez czas trwania sesji.
W pliku Modelfile. Ta metoda trwale zapisuje wartość w nazwanym modelu, dzięki czemu każdy klient korzysta z niej bez konieczności wprowadzania zmian po stronie klienta.
FROM llama3.1:8b
PARAMETER num_ctx 16384ollama create llama3.1-16k -f ./Modelfile
ollama run llama3.1-16kNa serwerze. OLLAMA_CONTEXT_LENGTH ustawia wartość domyślną dla każdego żądania, które nie zawiera własnego parametru num_ctx. W systemd należy dodać plik typu drop-in zamiast edytować główny plik jednostki.
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_CONTEXT_LENGTH=16384"sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama psKolejność pierwszeństwa ma kluczowe znaczenie podczas debugowania klienta zewnętrznego. Żądanie zawierające num_ctx nadpisuje ustawienie domyślne serwera, więc interfejs czatu lub agent wysyłający własną, niską wartość, może nieświadomie unieważnić zmianę wprowadzoną w systemd. Gdy konfigurujesz agenta programistycznego do pracy z serwerem Ollama, sprawdź, co wysyła klient, zanim przypiszesz winę serwerowi.
Dlaczego nie można po prostu ustawić num_ctx na maksimum modelu
Mechanizm atencji sprawia, że każdy token analizuje wszystkie poprzednie tokeny. Klucze i wartości obliczone dla wcześniejszych tokenów są przechowywane, aby nie trzeba było ich ponownie wyliczać dla każdego nowego tokenu; ten magazyn to KV cache (pamięć podręczna kluczy/wartości). Jest ona alokowana dla całego num_ctx w momencie ładowania modelu, a nie w miarę rozwoju konwersacji, więc duży kontekst zajmuje pamięć nawet przy jednowierszowym zapytaniu.
Samouczek DigitalOcean dotyczący kosztów wnioskowania przedstawia obliczenia w jednym wierszu:
kv_bytes_per_token = 2 * layers * kv_heads * head_dim * bytes_per_valueLiczba 2 uwzględnia osobno klucze i wartości. Pozostałe liczby należy odczytać z parametrów własnego modelu.
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 posiada 32 warstwy i 8 głowic kluczy/wartości. Wymiar głowicy to embed podzielone przez heads, czyli w tym przypadku 4096 / 32 = 128; niektóre modele publikują tę wartość bezpośrednio jako llama.attention.key_length. Domyślna pamięć podręczna przechowuje wartości f16, więc bytes_per_value wynosi 2, a działanie 2 32 8 128 2 daje 131 072 bajty. Jest to 128 KiB pamięci podręcznej na każdy pojedynczy token kontekstu. Pomnóż to przez długość kontekstu, a koszt przestanie być abstrakcyjny.
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
}
]Wiersze 6 wynikają z powyższego wzoru, a nie z pomiarów. Kolumna sumy dodaje 4,9 GB pobierania, które biblioteka Ollama wykazała dla llama3.1:8b w sierpniu 2026 roku, co daje 4,6 GiB, i pomija bufory obliczeniowe oraz sam proces serwera. Należy traktować to jako wartość minimalną.
Kluczowe znaczenie ma skala. Przy 8k pamięć podręczna kosztuje 1 GiB, co jest wartością pomijalną w porównaniu z wagami. Przy pełnym kontekście modelu 128k kosztuje ona 16 GiB, czyli ponad trzy razy więcej niż wagi, co daje łącznie blisko 20.6 GiB. Zatem serwer VPS o pojemności 4 GB nie jest w stanie załadować tego modelu z żadnym użytecznym kontekstem. Serwer VPS o pojemności 8 GB pozwala na komfortową pracę przy 8k. Serwer VPS o pojemności 16 GB osiąga 32k, pozostawiając miejsce na działanie pozostałych usług. Każdy z tych progów przesuwa się wraz z wagami, więc jeśli porównujesz większy model z tym 8B, te same obliczenia wykonane dla modelu Qwen 27B na serwerze VPS tylko z procesorem pokazują, jak niewiele miejsca wagi pozostawiają na kontekst w przedziale od 8 do 64 GB pamięci RAM.
Co się dzieje, gdy pamięć podręczna KV nie mieści się w pamięci
Na serwerze VPS korzystającym wyłącznie z procesora (CPU) proces po prostu zwiększa swoje zapotrzebowanie na pamięć. Należy monitorować ten proces podczas ładowania modelu oraz w trakcie przetwarzania długiego żądania.
free -m
ps -eo rss,comm --sort=-rss | head -n 5Wartość RSS (resident set size) jest wyświetlana w kilobajtach. Jeśli użycie partycji wymiany (swap) w free -m zaczyna rosnąć, należy zmniejszyć rozmiar kontekstu. Pamięć podręczna KV znajdująca się w swapie powoduje, że generowanie tokenów zatrzymuje się na sekundy, ponieważ każdy nowy token wymaga odczytania całej pamięci podręcznej.
Jeśli w systemie całkowicie zabraknie pamięci, jądro wybierze największy proces i go zakończy (OOM Killer).
sudo dmesg | grep -i "killed process"Wiersz zawierający Out of memory: Killed process 1234 (ollama) oznacza, że żądany kontekst nie zmieścił się w pamięci. Ollama często odrzuca żądanie, zanim do tego dojdzie, a operacja kończy się błędem informującym o ilości wymaganej pamięci w zestawieniu z ilością pamięci dostępnej.
Na serwerze z procesorem graficznym (GPU) awaria przebiega mniej gwałtownie. Warstwy modelu są przenoszone do pamięci RAM systemu, ollama ps pokazuje podział między CPU a GPU, a przepustowość drastycznie spada. Skala spadku zależy od używanego sprzętu, dlatego należy zmierzyć liczbę tokenów na sekundę na własnym serwerze dla każdego ustawienia kontekstu, zamiast polegać na wynikach uzyskanych na innej maszynie.
Czas przetwarzania wstępnego (prefill) rośnie szybciej niż długość promptu
Prefill to praca wykonywana nad danymi wejściowymi przed wygenerowaniem pierwszego tokena wyjściowego. Każdy token promptu odnosi się do wszystkich poprzedzających go tokenów, dlatego całkowita ilość pracy rośnie kwadratowo względem długości danych wejściowych. Podwojenie długości promptu powoduje ponad dwukrotny wzrost czasu oczekiwania na pierwszy token.
Odpowiedź zawiera pomiar, więc nie trzeba polegać na szacunkach.
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)}'Uruchom to z krótkim promptem, a następnie ponownie z długim promptem, po czym w obu przypadkach podziel liczbę tokenów przez czas w sekundach. Na VPS bez GPU prefill jest zwykle najwolniejszym etapem obsługi żądania z długim kontekstem, a wartość tokens per second zmierzona dla krótkiego promptu nie pozwala przewidzieć tego czasu. Prefill, który trwa dłużej niż ustawiony przed nim timeout, jest zazwyczaj przyczyną zwrócenia komunikatu przekroczono termin wykonania kontekstu zamiast odpowiedzi dla długiego promptu. Dlatego przed skróceniem kontekstu ustal, która warstwa przerwała operację.
Współbieżność jest obszarem, w którym ten problem jest najbardziej odczuwalny. Każde obsługiwane żądanie wymaga własnej pamięci podręcznej, więc pamięć wskazana na powyższym wykresie dotyczy pojedynczego żądania, a nie całego serwera. Jedno długie żądanie może zablokować zasoby serwera, podczas gdy krótkie żądania będą czekać w kolejce. Wartość OLLAMA_NUM_PARALLEL należy ustawiać świadomie i zapoznać się z artykułem ilu współbieżnych użytkowników może obsłużyć jeden samodzielnie hostowany LLM przed jednoczesnym zwiększeniem obu parametrów.
Odzyskiwanie kontekstu przy mniejszej pamięci podręcznej
bytes_per_value we wzorze to ustawienie, którym można sterować. FAQ Ollama dokumentuje OLLAMA_KV_CACHE_TYPE, gdzie f16 jest wartością domyślną wynoszącą 2 bajty, dodatkowo q8_0 wynosi 1 bajt, a q4_0 to wartości poniżej tego poziomu. Przejście na q8_0 zmniejsza pamięć podręczną o połowę, więc wiersz 32k zajmuje 2 GiB zamiast 4 GiB. Kwantyzacja wag zwalnia pamięć z drugiej strony tego samego budżetu, a tag GLM, który faktycznie mieści się na VPS jest opracowywany krok po kroku poprzez kolejne poziomy kwantyzacji, jeśli jest to kompromis, który wolisz wybrać. To samo FAQ dokumentuje OLLAMA_FLASH_ATTENTION=1, którego niektóre kompilacje wymagają, zanim kwantyzowana pamięć podręczna zacznie działać.
[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"Potwierdzaj zamiast zakładać: zrestartuj usługę, załaduj model przy tym samym num_ctx co poprzednio i porównaj RSS. Wsparcie zależy od modelu oraz backendu, więc ustawienie, które nic nie zmienia, oznacza, że Twoja konfiguracja nie jest obsługiwana. Dokumentacja wymienia te opcje bez gwarancji uzyskania jakościowego wyniku, więc przetestuj q4_0 na własnych promptach, zanim zaczniesz na nich polegać. Jeśli to właśnie te parametry są powodem Twojej obecności tutaj, Ollama i llama.cpp udostępniają je w różny sposób.
Przepis na dobór num_ctx
- Odczytaj maksymalny kontekst modelu, liczbę warstw oraz liczbę głowic klucza/wartości z
/api/show. - Oblicz liczbę bajtów na token za pomocą wzoru, a następnie pomnóż przez pożądaną długość kontekstu.
- Dodaj rozmiar wag, porównaj z dostępną pamięcią RAM i zachowaj co najmniej 1 GiB zapasu dla pozostałych procesów systemowych.
- Ustaw wartość, załaduj model, a następnie potwierdź zastosowane parametry za pomocą
ollama psorazprompt_eval_count. - Uruchom właściwe zadanie, monitorując
free -m, i zmniejsz kontekst o połowę, jeśli zacznie być używana partycja swap.
Większość zadań wymaga mniejszego kontekstu, niż zazwyczaj się zakłada. Streszczenie długiego raportu mieści się w 16k. Interfejs wyszukiwania, który wkleja pięć fragmentów dokumentów, rzadko przekracza 8k. Agent programistyczny czytający całe pliki to przypadek, który faktycznie wymaga 64k lub więcej; jest to również sytuacja, w której należy dobrać parametry maszyny pod kątem kontekstu, a nie odwrotnie. Jeśli serwer jest nowy, zacznij od działającej instalacji Ollama na VPS i dostosuj kontekst, gdy modele będą się poprawnie ładować.
FAQ
Jaka jest domyślna długość kontekstu w Ollama?
Zależy to od kompilacji oraz sprzętu, dlatego należy to sprawdzić, zamiast zakładać wartość. FAQ Ollama podaje 4096 tokenów, dokumentacja Modelfile wskazuje na num_ctx domyślnie 2048, a strona dotycząca długości kontekstu opisuje wartość domyślną dobieraną na podstawie dostępnej pamięci VRAM: 4k poniżej 24 GiB, 32k od 24 do 48 GiB oraz 256k powyżej. Serwer VPS działający wyłącznie na CPU otrzymuje najniższą wartość. ollama ps wyświetla zastosowany kontekst w kompilacjach zawierających tę kolumnę, a prompt_eval_count w odpowiedzi API potwierdza to w każdej kompilacji.
Dlaczego Ollama ignoruje początek mojego długiego promptu?
Ponieważ prompt był dłuższy niż okno kontekstowe, więc serwer uciął go, zanim model go przetworzył, nie zwracając przy tym błędu. Wyślij ten sam prompt ponownie z większym num_ctx i obserwuj, jak rośnie prompt_eval_count w odpowiedzi. Jeśli ta liczba się nie zmienia, coś pomiędzy Tobą a serwerem samodzielnie ustawia num_ctx, co jest częstym zjawiskiem w przypadku interfejsów czatowych i frameworków agentowych.
Ile dodatkowej pamięci RAM wymaga większe num_ctx?
Pomnóż długość kontekstu przez koszt pamięci podręcznej na token, który wynosi 2 * layers * kv_heads * head_dim * bytes_per_value. Dla modelu Llama 3.1 8B w formacie f16 jest to 128 KiB na token, więc 32k tokenów kosztuje 4 GiB, a pełne 128k kosztuje 16 GiB ponad wagami modelu. Pamięć podręczna jest alokowana w momencie ładowania modelu, więc duże num_ctx zajmuje tę pamięć nawet wtedy, gdy Twoje prompty pozostają krótkie.
Czy większe okno kontekstowe spowalnia Ollama?
Tak, na dwa sposoby. Praca związana z prefill rośnie wraz z kwadratem długości promptu, więc długie dane wejściowe opóźniają pierwszy token bardziej, niż sugerowałaby sama długość. Większa pamięć podręczna konkuruje również o zasoby pamięci: na serwerze z GPU wypycha warstwy do pamięci RAM systemu, a na serwerze z samym CPU zbliża maszynę do użycia swapu. Duże num_ctx, którego nigdy nie wypełnisz, nadal zajmuje pamięć, choć nie wpływa na czas prefill.
Czy mogę ustawić num_ctx na stałe dla jednego modelu?
Tak. Utwórz plik Modelfile zawierający FROM llama3.1:8b oraz PARAMETER num_ctx 16384, a następnie uruchom ollama create llama3.1-16k -f ./Modelfile. Każdy klient, który wywoła llama3.1-16k, otrzyma ten kontekst bez konieczności przesyłania jakichkolwiek opcji. Żądanie zawierające własne num_ctx nadal ma pierwszeństwo, więc ustawienie to stanowi wartość domyślną, a nie limit górny.