SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-21

Jak ustawić reasoning effort w lokalnym modelu LLM

Dowiedz się, jak parametr reasoning effort wpływa na czas generowania odpowiedzi w lokalnych modelach. Sprawdź, ile tokenów zajmuje proces myślowy i jak optymalizować sprzęt.

Jak zmienia się nakład pracy modelu przy lokalnym LLM

Nakład pracy modelu (reasoning effort) to ustawienie określające, jak długo model ma analizować zagadnienie przed udzieleniem odpowiedzi. Zmienia ono wyłącznie długość segmentu rozumowania. Wagi na dysku pozostają identyczne na każdym poziomie, kwantyzacja jest taka sama, a odpowiedź generowana jest w tym samym przebiegu (forward pass). Zmienia się jedynie liczba tokenów, które model poświęca na własny notatnik przed przystąpieniem do odpowiedzi.

To rozróżnienie jest istotne ze względu na miejsce, w którym te tokeny są przetwarzane. W przypadku hostowanego API tokeny rozumowania są uwzględniane na fakturze. Na własnym VPS płaci się za nie czasem generowania na własnym CPU lub GPU oraz zajętym miejscem w oknie kontekstowym. Model ustawiony na najwyższy poziom wysiłku może poświęcić większość wyjścia na rozumowanie, zanim pojawi się pierwsze słowo odpowiedzi. Na własnym sprzęcie oznacza to różnicę między dwusekundową a dwuminutową reakcją.

Gdzie znajduje się poziom: szablon czatu, a nie wagi

Model myślący jest trenowany do generowania segmentu rozumowania, zazwyczaj zawartego w znacznikach <think> oraz </think>, przed udzieleniem ostatecznej odpowiedzi. Poziom wysiłku to instrukcja, którą szablon czatu modelu zapisuje w prompcie. Szablon ten jest plikiem Jinja dostarczanym wraz z modelem. Odczytuje on zmienną taką jak reasoning_effort i renderuje inną linię na poziomie systemowym dla każdej wartości, a model został wytrenowany do skracania lub wydłużania swojego brudnopisu w odpowiedzi na tę linię.

Wynikają z tego dwie kwestie. Nazwy poziomów należą do modelu, a nie do środowiska uruchomieniowego, więc nazwa z karty jednego modelu może nic nie znaczyć dla innego. Jeśli cokolwiek w łańcuchu zamieni szablon czatu modelu na ogólny, zmienna nigdy nie zostanie wyrenderowana, a ustawienie po cichu nie przyniesie żadnego efektu.

Sprawdzono w dniu 2026-08-20: karta modelu Qwen3.8-27B dokumentuje trzy poziomy wysiłku: low, medium oraz xhigh, przy czym xhigh jest wartością domyślną. Nie istnieje high. Samo myślenie jest przełączane za pomocą enable_thinking, co jest domyślnie włączone; karta dokumentuje również preserve_thinking, również domyślnie włączone, co zachowuje rozumowanie z wcześniejszych tur historii konwersacji. gpt-oss używa zamiast tego low, medium oraz high. Wiele innych rodzin modeli akceptuje jedynie wartość logiczną i nic więcej. Należy przeczytać kartę dla konkretnej pobranej wersji, ponieważ nazwy te nie stanowią standardu. Uruchamianie modelu 27B na VPS jest priorytetem. Ta strona dotyczy tego, co ustawić, gdy model już odpowiada.

Dlaczego duże obciążenie kosztuje więcej na VPS

Tokeny wyjściowe. Tokeny rozumowania są generowanymi tokenami. Przechodzą one przez tę samą pętlę dekodowania co odpowiedź, z prędkością tokenów na sekundę, na jaką pozwala sprzęt. Załóżmy, że zadanie generuje 200 tokenów odpowiedzi i 4000 tokenów rozumowania. Wygenerowano 4200 tokenów, a czytelnik zobaczył 200 z nich. Szybkość dekodowania jest określona przez przepustowość pamięci oraz przez wybraną kwantyzację, więc jedynym dostępnym parametrem pozostaje sama liczba tokenów.

Czas rzeczywisty. Użytkownik czeka na pierwszy token odpowiedzi, ponieważ wszystko przed nim to pusty ekran lub animacja ładowania. Rozumowanie jest emitowane jako pierwsze, więc czas oczekiwania to w przybliżeniu liczba tokenów rozumowania podzielona przez szybkość dekodowania, powiększona o czas przetwarzania promptu. Podwojenie długości rozumowania podwaja ten czas oczekiwania.

Kontekst. Tokeny rozumowania zajmują okno kontekstowe tak samo jak każdy inny token. Przy włączonym preserve_thinking, notatnik z pierwszej tury nadal znajduje się w prompcie w piątej turze, więc przetwarzanie promptu staje się wolniejsze z każdą turą, podczas gdy okno zapełnia się z obu stron. Zwiększenie num_ctx w celu jego utrzymania zużywa pamięć podręczną KV, która na serwerze VPS bez GPU jest pamięcią RAM systemu, której użytkownik może nie mieć w nadmiarze.

Kiedy zwiększyć poziom, a kiedy pozostawić go na niskim poziomie

Zwiększ poziom w przypadku zadań, w których błędny krok pośredni prowadzi do niepoprawnego wyniku: wieloetapowe obliczenia arytmetyczne i konwersja jednostek, planowanie edycji w wielu plikach, kod wymagający kompilacji oraz problemy z ograniczeniami, gdzie jedna odpowiedź musi spełniać jednocześnie kilka warunków. W takich sytuacjach notatnik wykonuje rzeczywistą pracę, a dłuższy proces myślowy jest tanim sposobem na wykrycie błędu, który model w przeciwnym razie by utrwalił.

Pozostaw poziom na niskim poziomie, gdy odpowiedź znajduje się już w danych wejściowych, a zadanie polega na jej przetworzeniu. Ekstrakcja, klasyfikacja, tagowanie, tłumaczenie, przepisywanie, podsumowywanie i formatowanie należą do tej kategorii. Segment rozumowania w takich przypadkach głównie powtarza zadanie i daje modelowi przestrzeń do odrzucenia poprawnego, pierwszego instynktu.

Pozostaw poziom na niskim poziomie również w przypadku wszelkich zadań interaktywnych. W oknie czatu lub edytorze użytkownik znajduje się w pętli zwrotnej, więc szybka odpowiedź, którą można poprawić, jest lepsza niż wolna, na którą trzeba czekać. To jest rzeczywisty kompromis stojący za skierowaniem agenta programistycznego na model lokalny: agent wykonuje wiele małych wywołań, a koszt rozumowania jest naliczany przy każdym z nich.

Jak ustawić poziom w llama.cpp

llama.cpp zapisuje zmienną bezpośrednio w szablonie, co czyni go środowiskiem wykonawczym, w którym można mieć pewność, że poziom został poprawnie przekazany. Wskaż -m na posiadany plik GGUF.

llama-server -m ./qwen3.8-27b-Q4_K_M.gguf \
  --jinja \
  --reasoning-effort medium \
  --reasoning-format deepseek \
  -c 32768 \
  --host 127.0.0.1 --port 8080

--jinja korzysta z wbudowanego szablonu czatu modelu i jest domyślnie włączone w aktualnych kompilacjach. --reasoning-effort przyjmuje default, minimal, low, medium, high, xhigh lub max, przy czym default oznacza pozostawienie domyślnego ustawienia szablonu bez zmian. Ta lista jest słownikiem llama.cpp, a nie modelu, dlatego należy podawać wyłącznie nazwy wymienione przez kartę: poziom niezdefiniowany w szablonie może wywołać błąd szablonu w momencie wysyłania żądania. --reasoning-format deepseek przenosi proces rozumowania z message.content do message.reasoning_content, co sprawia, że podział ten jest mierzalny w następnej sekcji.

Aby wyłączyć myślenie zamiast je skracać, należy samodzielnie ustawić zmienną szablonu:

llama-server -m ./qwen3.8-27b-Q4_K_M.gguf --jinja \
  --chat-template-kwargs '{"enable_thinking": false}'

--reasoning-budget to inny mechanizm. Ogranicza on segment rozumowania w tokenach, przy czym 0 kończy go natychmiast, a -1 pozostawia go bez ograniczeń, zamiast prosić model o zaplanowanie krótszego procesu. Obie flagi działają w skali całego serwera. llama-server nie przyjmuje reasoning_effort jako pola dla pojedynczego żądania, więc obsługa dwóch poziomów wysiłku jednocześnie wymaga uruchomienia dwóch procesów na dwóch różnych portach.

vLLM udostępnia tę samą zmienną dla każdego żądania, wewnątrz treści zgodnej z OpenAI:

{"model": "Qwen/Qwen3.8-27B",
 "messages": [{"role": "user", "content": "Summarise this changelog in two lines."}],
 "chat_template_kwargs": {"reasoning_effort": "medium"}}

Jak ustawić poziom w Ollama

Ollama posiada własne pole, think, w /api/chat oraz /api/generate. Akceptuje ono true, false lub jedną z wartości low, medium, high i max, przy czym max żąda najwyższego poziomu oferowanego przez model. Funkcja myślenia (thinking) jest domyślnie włączona dla modeli, które ją wspierają.

ollama run qwen3.8:27b --think=low "Draft a one line commit message for a README typo fix"
{"model": "qwen3.8:27b",
 "messages": [{"role": "user", "content": "Which HTTP status code means the request body was too large?"}],
 "think": "low",
 "stream": false}

Proces wnioskowania zwracany jest w message.thinking, a odpowiedź w message.content; dane te są już rozdzielone. Wewnątrz interaktywnej sesji ollama run, polecenia /set think oraz /set nothink przełączają tę funkcję bez konieczności restartu.

Należy zwrócić uwagę na rozbieżność. Słownik Ollama obejmuje wartości low, medium, high oraz max. Szablon modelu Qwen3.8 definiuje natomiast low, medium oraz xhigh. Konieczne jest odwzorowanie jednej skali na drugą. Model Ollama zawiera szablon spakowany wewnątrz swojego tagu, a nie plik Jinja z oryginalnego repozytorium, dlatego to, czy wybrany poziom faktycznie dociera do modelu, zależy od tego spakowanego szablonu. Nie należy zakładać, że konfiguracja zadziałała automatycznie. Weryfikacja zajmuje około minuty.

Jak zmierzyć, czy poziom faktycznie został zastosowany

Wyślij to samo zapytanie na więcej niż jednym poziomie z temperature ustawionym na 0, a następnie porównaj liczbę tokenów. W tym miejscu jq buduje treść, dzięki czemu nie trzeba ręcznie uciekać cudzysłowów.

for level in low medium max; do
  body=$(jq -n --arg lvl "$level" '{
    model: "qwen3.8:27b",
    messages: [{role: "user", content: "A pump fills a 4500 litre tank in 25 minutes. A second pump is 40 percent slower. How long do both together take? Answer in minutes."}],
    think: $lvl,
    stream: false,
    options: {temperature: 0, num_ctx: 8192}
  }')
  echo "== $level"
  curl -s http://localhost:11434/api/chat -d "$body" | jq '{
    thinking_chars: (.message.thinking // "" | length),
    answer_chars: (.message.content | length),
    eval_count: .eval_count,
    seconds: (.total_duration / 1e9),
    tok_per_sec: (.eval_count / (.eval_duration / 1e9))
  }'
done

eval_count to każdy wygenerowany token, wliczając w to rozumowanie, więc różnica między dwoma poziomami to niemal w całości proces myślowy. thinking_chars podaje bezpośrednio podział. Dwie rzeczy powinny być prawdziwe: liczby zmieniają się między poziomami, a odpowiedź pozostaje poprawna na niższym z nich. Jeśli eval_count mieści się w granicach szumu statystycznego we wszystkich trzech uruchomieniach, poziom jest ignorowany. Rozwiązaniem jest środowisko uruchomieniowe, które przekazuje ten parametr, zamiast zmiany nazwy poziomu.

Całkowity czas to tylko połowa sukcesu, dlatego należy zmierzyć czas do pierwszego tokena odpowiedzi poprzez strumieniowanie i zatrzymanie na pierwszym niepustym fragmencie content. Wymaga to użycia jq oraz bc.

start=$(date +%s.%N)
curl -sN http://localhost:11434/api/chat -d '{
  "model": "qwen3.8:27b",
  "messages": [{"role": "user", "content": "Explain what a reverse proxy does, in three sentences."}],
  "think": "low",
  "stream": true
}' |
while IFS= read -r line; do
  if [ -n "$(printf '%s' "$line" | jq -r '.message.content // ""')" ]; then
    echo "first answer token after $(echo "$(date +%s.%N) - $start" | bc)s"
    break
  fi
done

Uruchom to z low, a następnie ponownie z max. Różnica to czas oczekiwania, który zyskujesz. W llama.cpp te same liczby wracają wewnątrz odpowiedzi, więc nie jest potrzebna arytmetyka powłoki:

curl -s http://localhost:8080/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model": "local", "temperature": 0,
       "messages": [{"role": "user", "content": "A pump fills a 4500 litre tank in 25 minutes. A second pump is 40 percent slower. How long do both together take?"}]}' | jq '{
  reasoning_chars: (.choices[0].message.reasoning_content // "" | length),
  answer_chars: (.choices[0].message.content | length),
  predicted_n: .timings.predicted_n,
  tok_per_sec: .timings.predicted_per_second
}'

Wykonaj to na własnej maszynie. Opublikowane porównania wydajności mierzono na sprzęcie, który nie jest Twój, a Twój wskaźnik dekodowania to wartość, która zamienia liczbę tokenów na sekundy. Pomiar tokenów na sekundę na własnym serwerze pozwala uzyskać tę wartość: liczba tokenów rozumowania podzielona przez Twój wskaźnik dekodowania to czas oczekiwania, który właśnie dodano.

Co może pójść nie tak

Odpowiedź jest ucięta lub content jest puste, podczas gdy thinking jest pełne. Limit generowania został wyczerpany przez proces wnioskowania. Parametr num_predict w Ollama ogranicza całą generację, wliczając w to wnioskowanie, a ponieważ wnioskowanie odbywa się w pierwszej kolejności, limit 512 tokenów przy wysokim poziomie wysiłku może zakończyć odpowiedź przed wygenerowaniem właściwej treści. Ollama zgłasza w takiej odpowiedzi "done_reason": "length". Należy zwiększyć limit lub obniżyć poziom wysiłku. Jak num_predict zlicza tokeny szczegółowo opisuje tę zależność.

Poziom nie zmienia niczego. Liczba tokenów jest identyczna na każdym poziomie. Albo środowisko uruchomieniowe nie przekazuje zmiennej, albo szablon jej nie odczytuje. Należy sprawdzić szablon, którego faktycznie używa środowisko uruchomieniowe, zamiast tego z oryginalnego repozytorium. Narzędzie llama.cpp z parametrami --jinja oraz --chat-template-kwargs wpisuje zmienną ręcznie, więc stanowi dobry punkt odniesienia: jeśli poziom działa w tym przypadku, a w innych nie, oznacza to, że model jest poprawny, a problem leży po stronie środowiska uruchomieniowego, które pomija zmienną.

Nazwa poziomu jest odrzucana. Błąd szablonu w momencie żądania lub awaria przy pierwszej wiadomości na serwerze, który poza tym działa poprawnie, zazwyczaj oznacza przekazanie poziomu, którego szablon nie definiuje, na przykład high dla modelu, którego karta zawiera tylko wartości low, medium oraz xhigh.

Wielokrotne tury czatu spowalniają każdą kolejną odpowiedź. Stare wnioskowanie jest przechowywane w historii. Należy ustawić preserve_thinking na false, jeśli model to obsługuje, lub usunąć pole thinking z wiadomości odsyłanych do modelu. W przeciwnym razie czas przetwarzania promptu rośnie z każdą turą, mimo że długość odpowiedzi pozostaje taka sama.

Jakość spada przy niskim poziomie wysiłku w zadaniu, które wydawało się proste. Niektóre zadania ekstrakcji nie są w rzeczywistości ekstrakcją. Jeśli dane wejściowe wymagają konwersji jednostek lub zastosowania reguł w określonej kolejności, jest to zadanie wymagające wnioskowania z krótkim wynikiem. W takim przypadku należy zwiększyć poziom dla konkretnego wywołania, zamiast dla całego serwera.

Uruchamianie dwóch poziomów jednocześnie

llama.cpp ustala poziom podczas uruchamiania, więc serwer obsługujący jednocześnie edytor i nocne zadania wsadowe wymaga dwóch procesów na dwóch portach, z których każdy posiada własny --reasoning-effort. Dwa procesy oznaczają również dwie kopie wag w pamięci, chyba że zadania zostaną rozdzielone w czasie. Na jednym VPS tańszym rozwiązaniem jest zazwyczaj serwer o niskim obciążeniu dla zadań interaktywnych oraz zaplanowane uruchomienie o wyższym obciążeniu dla zadań, na których wynik nikt nie czeka. Zasada Co się dzieje, gdy kilku użytkowników współdzieli jeden lokalny model ma tutaj również zastosowanie: tokeny rozumowania to praca dekodowania, więc zwiększenie wysiłku redukuje efektywną współbieżność w przybliżeniu o ten sam współczynnik, o jaki wzrasta liczba tokenów.

FAQ

Jakiego poziomu wysiłku wnioskowania należy używać domyślnie?

Należy zacząć od najniższego poziomu oferowanego przez model i zwiększać go tylko w przypadku zadań, które zakończyły się niepowodzeniem. Kilka modeli wnioskujących ma ustawiony wysoki poziom domyślny, a Qwen3.8-27B od sierpnia 2026 roku domyślnie korzysta z xhigh, czyli najwyższego poziomu. To ustawienie wybrano, aby uzyskać lepsze wyniki w tabelach benchmarkowych, a tabele te nie uwzględniają kosztu czasu. Na własnym sprzęcie płaci się czasem oczekiwania, dlatego wyższy poziom powinien być wybierany świadomie dla konkretnego zadania, a nie jako ustawienie dziedziczone przez każde zapytanie.

Czy tokeny wnioskowania wliczają się do okna kontekstowego?

Tak. Są to zwykłe tokeny w wyjściu, które zajmują miejsce w oknie kontekstowym wraz z pozostałą treścią. To, czy pozostaną tam w kolejnej turze, zależy od środowiska uruchomieniowego i modelu. Dokumentacja Qwen3.8 opisuje preserve_thinking, włączone domyślnie, co powoduje zachowanie wcześniejszego wnioskowania w historii, więc długa konwersacja przenosi każdy wygenerowany brudnopis. Należy ustawić tę wartość na false lub usunąć pole thinking z wiadomości przesyłanych ponownie, aby zatrzymać wzrost zużycia okna kontekstowego.

Dlaczego zmiana poziomu wnioskowania nie wpływa na liczbę tokenów?

Ustawienie nie dociera do szablonu czatu. Poziom jest zmienną szablonu, więc działa tylko wtedy, gdy środowisko uruchomieniowe ją przekaże, a spakowany szablon ją odczyta. Niektóre środowiska uruchomieniowe dostarczają własny szablon zamiast pliku Jinja z oryginalnego repozytorium, przez co zmienna jest pomijana bez wyświetlenia błędu. Można to zweryfikować, wysyłając to samo zapytanie na najniższym i najwyższym poziomie z temperature ustawionym na 0 i porównując eval_count. Jeśli liczby są zbliżone w granicach błędu statystycznego, poziom jest ignorowany.

Czy mniejszy wysiłek wnioskowania obniża dokładność modelu?

Zależy to od zadania i warto to zmierzyć, zamiast zakładać z góry. W przypadkach, gdy odpowiedź znajduje się już w danych wejściowych, takich jak ekstrakcja lub przepisywanie, krótszy brudnopis zazwyczaj nic nie zmienia. W sytuacjach, gdzie krok pośredni musi być poprawny przed wykonaniem kolejnego, na przykład w wieloetapowych obliczeniach arytmetycznych lub kodzie, który musi się skompilować, dokładność spada wraz z krótszym brudnopisem. Należy przygotować zestaw dwudziestu zapytań z rzeczywistego obciążenia, uruchomić je na dwóch poziomach z temperature ustawionym na 0 i policzyć błędne odpowiedzi. Ta liczba jest specyficzna dla danego obciążenia i żadna opublikowana tabela jej nie dostarczy.