SSD Nodes Learn Hosting plans →
Посібники Matt ConnorВід Matt Connor · Оновлено 2026-09-01

Рівні міркування локальної LLM: вплив на швидкість

Дізнайтеся, як рівень міркування змінює довжину scratchpad, час генерації та контекст на власному CPU або GPU: від 2 секунд до 2 хвилин.

Які зміни вносить рівень міркування в локальній LLM

Рівень міркування — це параметр, який визначає, скільки часу модель міркує перед відповіддю. Він змінює лише довжину сегмента міркування. Ваги моделі на диску однакові на кожному рівні, квантизація також однакова, а відповідь формується під час того самого forward pass. Змінюється лише кількість токенів, які модель спочатку витрачає на власний scratchpad.

Ця відмінність важлива через те, де враховуються ці токени. У hosted API токени міркування відображаються у рахунку. На VPS, яким ви керуєте, вони оплачуються часом генерації на власному CPU або GPU та місцем у контекстному вікні. Якщо залишити для моделі найвищий рівень міркування, вона може витратити більшу частину виводу на міркування, перш ніж з’явиться перше слово відповіді. На self-hosted hardware це може означати різницю між відповіддю за дві секунди та відповіддю за дві хвилини.

Де зберігається рівень: у chat template, а не у weights

Thinking model навчають генерувати сегмент міркувань, зазвичай обгорнутий у теги <think> і </think>, перед фінальною відповіддю. Рівень зусиль — це інструкція, яку chat template моделі додає до prompt. Цей template — Jinja-файл, що постачається разом із моделлю. Він читає змінну на зразок reasoning_effort і формує окремий рядок на рівні system для кожного значення. Модель навчили відповідно скорочувати або подовжувати свій scratchpad.

З цього випливають два висновки. Назви рівнів належать моделі, а не runtime, тому назва з картки однієї моделі може нічого не означати для іншої. Якщо будь-який компонент у ланцюжку замінює chat template моделі на generic template, змінна не підставляється, а налаштування мовчки не працює.

Станом на 2026-08-20 у картці моделі Qwen3.8-27B задокументовано три рівні зусиль: low, medium і xhigh, причому xhigh є типовим. Значення high не існує. Сам режим міркувань перемикається параметром enable_thinking, який типово увімкнений. У картці також задокументовано preserve_thinking, увімкнений типово; він зберігає міркування з попередніх ходів у history розмови. Натомість gpt-oss використовує low, medium і high. Багато інших сімейств підтримують лише boolean-параметр без додаткових рівнів. Перевірте картку саме тієї версії, яку ви завантажили, оскільки ці назви не є стандартом. Спочатку прочитайте Як запустити модель 27B на VPS. Ця сторінка описує, що налаштувати після того, як модель почне відповідати.

Чому високі зусилля коштують дорожче на VPS

Кількість вихідних токенів. Токени міркування генеруються так само, як і токени відповіді. Вони проходять той самий цикл декодування з тією самою швидкістю, яку забезпечує ваше обладнання. Припустімо, що завдання генерує 200 токенів відповіді та 4,000 токенів міркування. Загалом генерується 4,200 токенів, але читач бачить лише 200. Швидкість декодування визначається пропускною здатністю пам’яті та вибраною квантизацією, тому єдиним доступним важелем залишається сама кількість токенів.

Час очікування. Користувач очікує на перший токен відповіді, оскільки до цього на екрані відображається порожній простір або згорнутий індикатор завантаження. Спочатку генеруються токени міркування, тому час очікування приблизно дорівнює кількості токенів міркування, поділеній на швидкість декодування, плюс час обробки промпту. Якщо подвоїти довжину міркування, цей час очікування також подвоїться.

Контекст. Токени міркування займають місце у вікні контексту так само, як і будь-які інші токени. Коли preserve_thinking увімкнено, робочі записи з першого ходу все ще містяться в промпті на п’ятому ході. Через це обробка промпту сповільнюється на кожному наступному ході, а вікно заповнюється з обох боків. Збільшення num_ctx для їх збереження потребує пам’яті для KV cache. На VPS без GPU це системна RAM, якої може не вистачити.

Коли підвищувати рівень, а коли залишати його низьким

Підвищуйте його для завдань, де неправильний проміжний крок спотворює результат: багатокрокові арифметичні обчислення та перетворення одиниць, планування змін у кількох файлах, коду, який має компілюватися, і задач з обмеженнями, де одна відповідь повинна одночасно задовольняти кілька умов. У таких випадках scratchpad виконує реальну роботу, а більша довжина міркувань є простим способом виявити помилку, яку модель інакше могла б не помітити.

Залишайте його низьким, коли відповідь уже міститься у вхідних даних, а завдання полягає в її перенесенні. Сюди належать вилучення даних, класифікація, додавання тегів, переклад, перефразування, узагальнення та форматування. Сегмент міркувань здебільшого лише повторює завдання і дає моделі можливість відмовитися від правильної першої відповіді.

Також залишайте його низьким для будь-яких інтерактивних завдань. У чаті або редакторі ви берете участь у процесі, тому швидка відповідь, яку можна виправити, краща за повільну, на яку доводиться чекати. Саме в цьому полягає компроміс, пов’язаний із підключенням coding agent до локальної моделі: агент виконує багато невеликих викликів, і витрати на міркування стягуються за кожен із них.

Як встановити рівень у llama.cpp

llama.cpp безпосередньо записує змінну в шаблон. Тому саме на цьому етапі можна перевірити, що рівень було передано. Вкажіть у -m наявний у вас файл 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 використовує власний chat template моделі та типово ввімкнений у поточних збірках. --reasoning-effort приймає default, minimal, low, medium, high, xhigh або max, де default означає не змінювати типове значення шаблону. Цей список належить до словника llama.cpp, а не моделі. Тому передавайте лише значення, наведене в картці моделі. Рівень, якого немає в шаблоні, може спричинити помилку шаблону під час обробки запиту. --reasoning-format deepseek переміщує міркування з message.content до message.reasoning_content. Завдяки цьому в наступному розділі можна виміряти їх окремо.

Щоб вимкнути міркування, а не лише скоротити його, задайте змінну шаблону вручну:

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

--reasoning-budget працює інакше. Цей параметр обмежує сегмент міркувань у токенах. Значення 0 негайно завершує його, а -1 не встановлює обмеження. Параметр не вказує моделі планувати коротший сегмент. Обидва прапорці діють для всього сервера. llama-server не приймає reasoning_effort як поле окремого запиту. Тому для одночасного обслуговування двох рівнів зусиль потрібні два процеси на двох портах.

vLLM відкриває ту саму змінну для кожного запиту в тілі, сумісному з OpenAI:

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

Як задати рівень в Ollama

В Ollama є власне поле think у /api/chat і /api/generate. Воно приймає true, false або одне зі значень low, medium, high і max, де max запитує найвищий рівень, який підтримує модель. Для моделей, що підтримують міркування, його ввімкнено за замовчуванням.

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}

Міркування повертається в message.thinking, а відповідь — у message.content, уже розділеними. В інтерактивному сеансі ollama run команди /set think і /set nothink вмикають або вимикають його без перезапуску.

Тепер зверніть увагу на невідповідність. В Ollama використовуються значення low, medium, high і max. У шаблоні Qwen3.8 визначено low, medium і xhigh. Одне значення потрібно зіставити з іншим. Модель Ollama містить шаблон усередині свого tag, а не Jinja-файл з оригінального репозиторію. Тому те, чи доходить заданий рівень до моделі, залежить від цього шаблону. Не припускайте, що все спрацювало. Перевірка займає близько хвилини.

Як перевірити, чи рівень справді застосовано

Надішліть той самий prompt на кількох рівнях із temperature зі значенням 0, а потім порівняйте кількість токенів. Тут jq формує тіло запиту, тому не потрібно вручну екранувати лапки.

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 — це кількість усіх згенерованих токенів, включно з токенами міркування, тому різниця між двома рівнями майже повністю припадає на міркування. thinking_chars одразу повертає цей розподіл. Має виконуватися дві умови: значення змінюються між рівнями, а відповідь залишається правильною вже на нижчому рівні. Якщо eval_count на всіх трьох запусках перебуває в межах похибки, рівень ігнорується. У такому разі потрібно використовувати runtime, який передає цей параметр, а не змінювати назву рівня.

Загальний час показує лише половину картини. Тому виміряйте час до першого токена відповіді, використовуючи streaming і зупиняючи його на першому непорожньому фрагменті content. Для цього потрібні jq і 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

Запустіть це зі значенням low, а потім зі значенням max. Різниця — це час очікування, який ви додаєте. У llama.cpp ті самі значення повертаються в response, тому обчислення в shell не потрібні:

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
}'

Виконайте це на власному сервері. Опубліковане порівняння продуктивності вимірювали на обладнанні, якого у вас немає, а ваша швидкість декодування визначає, як перетворити кількість токенів на секунди. Вимірювання токенів за секунду на власному сервері дає це значення: кількість токенів міркування, поділена на швидкість декодування, дорівнює часу очікування, який ви щойно додали.

Що може піти не так

Відповідь обривається або content порожнє, тоді як thinking заповнене. Ліміт генерації витрачено на міркування. Параметр num_predict в Ollama обмежує всю генерацію, включно з міркуваннями. Оскільки міркування генеруються першими, ліміт у 512 токенів за високого рівня може завершити відповідь ще до її початку. Ollama вказує "done_reason": "length" для цієї відповіді. Збільште ліміт або зменште рівень. У розділі Як num_predict підраховує токени детально описано цю взаємодію.

Рівень нічого не змінює. Кількість токенів однакова на кожному рівні. Це означає, що runtime не передає змінну або шаблон її не зчитує. Перевірте шаблон, який фактично використовує runtime, а не шаблон з оригінального репозиторію. llama.cpp з --jinja і --chat-template-kwargs записує змінну вручну, тому його зручно використовувати як контрольний варіант: якщо рівень працює там і не працює в інших місцях, проблема не в моделі, а інший runtime відкидає цю змінну.

Ім’я рівня відхиляється. Помилка шаблону під час виконання запиту або збій під час першого повідомлення за справного сервера зазвичай означає, що ви передали рівень, якого немає в шаблоні. Наприклад, high може бути не визначений для моделі, у картці якої зазначено лише low, medium і xhigh.

Багатотурові чати сповільнюються на кожному наступному ході. Старі міркування зберігаються в історії. Встановіть preserve_thinking у false, якщо модель це підтримує, або видаляйте поле thinking з повідомлень, які надсилаєте повторно. Інакше обсяг обробки промпту зростає на кожному ході, тоді як довжина відповідей залишається незмінною.

Якість погіршується за низького рівня на завданні, яке ви вважали простим. Деякі завдання на вилучення даних насправді не є простими завданнями на вилучення. Якщо вхідні дані потребують конвертації одиниць або послідовного застосування правила, це завдання на міркування з коротким результатом. Підвищте рівень лише для цього виклику, а не для всього сервера.

Одночасний запуск на двох рівнях

llama.cpp фіксує рівень під час запуску, тому сервер, який обслуговує і редактор, і нічне пакетне завдання, потребує двох процесів на двох портах. Кожен процес має власний --reasoning-effort. Два процеси також означають дві копії вагових коефіцієнтів у пам’яті, якщо не рознести ці завдання в часі. На одному VPS зазвичай вигідніше використовувати сервер із низьким рівнем зусиль для запитів, на які людина чекає, і запускати за розкладом із вищим рівнем зусиль завдання, за яким ніхто не стежить. Що відбувається, коли кілька користувачів спільно використовують одну локальну модель Це також стосується цього випадку: reasoning tokens — це робота декодування, тому збільшення рівня зусиль приблизно в такому самому співвідношенні зменшує ефективну кількість одночасних запитів, у якому збільшується кількість токенів.

FAQ

Який рівень міркування слід використовувати за замовчуванням?

Починайте з найнижчого рівня, який пропонує модель, і підвищуйте його лише для завдань, на яких ви вже спостерігали помилки. Деякі моделі з міркуванням постачаються з високим рівнем за замовчуванням, а Qwen3.8-27B станом на August 2026 за замовчуванням використовує xhigh, тобто максимальний рівень. Це значення обирають, щоб модель добре виглядала в таблицях бенчмарків. Таблиця бенчмарків не враховує вартість часу. На власному обладнанні ви платите секундами, тому вищий рівень має бути параметром, який ви вмикаєте для окремого завдання, а не налаштуванням для кожного запиту.

Чи враховуються токени міркування в розмірі контекстного вікна?

Так. Це звичайні токени у вихідних даних, і вони займають місце в контекстному вікні разом з усіма іншими даними. Чи залишаться вони в контексті наступного ходу, залежить від runtime і моделі. У картці Qwen3.8 задокументовано preserve_thinking, увімкнений за замовчуванням. Він зберігає попередні міркування в історії, тому довга розмова містить кожен створений моделлю чернетковий блок. Установіть значення false або вилучіть поле thinking із повідомлень, які ви передаєте повторно. Тоді обсяг обробки запитів перестане зростати.

Чому зміна рівня міркування не впливає на кількість моїх токенів?

Це налаштування не передається в chat template. Рівень є змінною шаблону, тому він працює лише тоді, коли runtime передає її, а упакований шаблон її зчитує. Деякі runtime постачають власний шаблон разом із моделлю замість Jinja-файлу з оригінального репозиторію. У такому разі змінна відкидається без повідомлення про помилку. Перевірте це, надіславши той самий запит на найнижчому та найвищому рівнях із temperature зі значенням 0 і порівнявши eval_count. Якщо кількість відрізняється лише в межах похибки, рівень ігнорується.

Чи знижує менший рівень міркування точність моделі?

Це залежить від завдання. Таке припущення краще перевірити вимірюванням. Якщо відповідь уже міститься у вхідних даних, наприклад під час вилучення або переформулювання тексту, коротша чернетка зазвичай нічого не змінює. Якщо перед отриманням остаточної відповіді потрібно правильно виконати проміжний крок, наприклад під час багатокрокових обчислень або роботи з кодом, який має скомпілюватися, точність із коротшою чернеткою знижується. Складіть набір із twenty запитів із вашого реального робочого навантаження, виконайте їх на двох рівнях із temperature зі значенням 0 і підрахуйте неправильні відповіді. Це число залежить від вашого робочого навантаження, і жодна опублікована таблиця не дасть його замість вас.