Перейти к содержанию
Публикация AiManual

Штраф за «wait» и «maybe»: как logit bias в llama.cpp повышает точность Qwen на разных квантизациях

Отрицательный logit bias -2 на слова «wait», «maybe» и «perhaps» поднял точность Qwen3.5-4B на MATH-500 во всех пяти GGUF-квантизациях, от BF16 до Q2_K, а цепоч

Коротко

Что будет в материале

  1. 01

    Что такое маркеры переосмысления и почему они мешают reasoning-моделям

  2. 02

    Как работает logit bias в llama.cpp: штраф -2 для нежелательных токенов

  3. 03

    Готовые команды для запуска теста в llama.cpp

  4. 04

    Результаты теста: точность и длина reasoning-токенов на квантизациях от BF16 до Q2_K

Отрицательный logit bias -2 на токены слов « wait», « maybe», « perhaps» и ещё нескольких десятков похожих поднял точность Qwen3.5-4B во всех пяти проверенных GGUF-квантизациях: на BF16 с 74% до 84%, на Q4_K_M с 60% до 66%, на Q2_K с 12% до 24%. Тест провёл участник сообщества r/LocalLLaMA на 50 случайных вопросах из MATH-500, с одной моделью и пятью квантизациями из репозитория bartowski/Qwen_Qwen3.5-4B-GGUF.

Механика простая. llama.cpp принимает флаг --logit-bias, который сдвигает логит конкретного токена перед сэмплированием. Штраф -2 не запрещает слово, а делает его маловероятным, поэтому модель реже уходит в цикл «подожди, а может, иначе». Дообучение не нужно, веса не меняются: приём training-free.

Автор сразу оговорил границы: один тест, одна модель, один набор вопросов. Ниже разберём, что именно подавляется, как собрать команду под свою модель и где штраф за «wait» скорее навредит, чем поможет.

Что такое маркеры переосмысления и почему они мешают reasoning-моделям

Термин ввели авторы статьи Meta arXiv 2606.00206 «Quantized Reasoning Models Think They Need to Think Longer, but They Do Not». Они собрали набор overthinking markers, слов, которыми модель сопровождает перепроверки и откаты: « perhaps», « maybe», « wait», « Wait», « actually», « hold», « Hmm», « hmm», « Alternatively», « alternatively», « However», « however», « instead», « Instead», « But», « but», « though», « although», « yet», « rather», « unless», « otherwise», « nonetheless», « nevertheless», « regardless», « still», « anyway», « Or», « or», « either», « whether», « uncertain», « unsure», « possibly», « might», « could», « another», « different», « reconsider», « rethink», « backtrack», « retry», « revisit», « doubt», « confused», « wrong», « mistake», « error», « incorrect».

В той же работе показано, что штраф на эти маркеры сокращает длину цепочки рассуждений на 12-23%, сохраняя или повышая точность. Проверка шла на 5 моделях от 1.5B до 32B параметров, 3 методах квантизации и 5 бенчмарках. Квантизации, которые поддерживает llama.cpp, в исследовании не разбирались.

Почему квантизация усиливает переосмысление

При округлении весов до 4 или 3 бит мелкие различия в числах теряются. Модель чаще промахивается на промежуточном шаге и тратит дополнительные циклы на перепроверку: возвращается назад, пробует другой путь, сомневается в уже полученном результате. Авторы Meta фиксируют это прямо: агрессивная посттренировочная квантизация (PTQ) снижает точность и одновременно увеличивает длину цепочки рассуждений. Отдельное наблюдение оттуда: до 52% ошибок квантизованных моделей выглядят так, что правильный ответ был достигнут по ходу рассуждения, но в финале модель выдала другой.

Как деградация выглядит на разных уровнях сжатия, разбирали отдельно, например на бенчмарке SWE-Verified.

Как работает logit bias в llama.cpp: штраф -2 для нежелательных токенов

Генерация токена в llama.cpp проходит три шага: модель считает логиты для всего словаря, softmax превращает их в вероятности, сэмплер выбирает токен. Флаг --logit-bias вклинивается между первым и вторым шагом: он прибавляет к логиту указанного токена заданное число. В нашем случае число отрицательное, -2, поэтому вероятность выбора токена падает, но нулевой не становится.

Разница принципиальная. Полный запрет токена сломал бы рассуждение там, где слово нужно: «but» часто вводит верное уточнение, а «however» отделяет рабочий путь от тупикового. Штраф -2 оставляет возможность выбрать слово, если альтернатив нет.

Второй нюанс: bias задаётся не строкой, а ID токена. Токенизатор BPE режет текст не по словам, поэтому « wait» с ведущим пробелом и «wait» в начале строки это разные токены с разными ID. Отсюда длинные цепочки флагов: --logit-bias 466-2 --logit-bias 694-2. Запись 466-2 читается как «ID 466, смещение -2», а не как арифметика.

Как подобрать ID токенов для своей модели

ID зависят от модели и версии токенизатора, поэтому копировать чужие числа для другой модели нельзя: можно случайно подавить совсем не те слова. Порядок такой:

  • Возьмите tokenizer своей модели: файл tokenizer.json или сам GGUF-файл.
  • Прогоните через токенизатор каждое слово из списка маркеров в двух вариантах: с ведущим пробелом и без, а для начала предложения ещё с заглавной буквы.
  • Проверьте, что полученный ID указывает именно на нужный токен, а не на фрагмент другого слова.

Для моделей семейства Qwen это делается через библиотеку transformers или утилитами из состава llama.cpp. Правило одно: сначала получили ID, потом запустили генерацию.

Готовые команды для запуска теста в llama.cpp

Базовый запуск: путь к GGUF-файлу, набор флагов --logit-bias и промпт. Автор теста гонял Qwen3.5-4B в квантизациях GGUF из репозитория bartowski, от BF16 до Q2_K. Оригинальное исследование квантизации llama.cpp не покрывало, пользовательский прогон появился именно как проверка этого пробела.

Пример полной команды с набором --logit-bias

./llama-cli \
  -m Qwen3.5-4B-Q4_K_M.gguf \
  -c 8192 -n 4096 --temp 0.6 \
  --logit-bias 466-2 --logit-bias 694-2 --logit-bias 1362-2 \
  -p 'Вопрос из MATH-500'

Список ID здесь иллюстративный. Это те же значения, что автор теста привёл как пример, но они привязаны к конкретной версии токенизатора Qwen3.5-4B. Для другой модели или другой ревизии набор собирается заново.

Синтаксис флага сверьте со своей сборкой: llama.cpp развивается быстро, и формат записи bias в версиях отличается. Быстрая проверка это ./llama-cli --help и поиск по строке logit-bias. Параметр -c задаёт размер контекста, -n ограничивает длину генерации. Для reasoning-режима -n лучше поднять с запасом, иначе ответ обрежется на середине рассуждения.

Результаты теста: точность и длина reasoning-токенов на квантизациях от BF16 до Q2_K

КвантизацияТочность без biasТочность со штрафом -2Прирост точностиИзменение reasoning-токенов
BF1674%84%+10 п.п.-19.4%
Q8_076%80%+4 п.п.-11.0%
Q4_K_M60%66%+6 п.п.-14.8%
Q3_K_M52%66%+14 п.п.-17.5%
Q2_K12%24%+12 п.п.-11.5%

Это заявленные результаты одного прогона на 50 вопросах, а не воспроизведённый бенчмарк. Автор теста сам оговаривает: одна модель, один набор вопросов, поэтому цифры нельзя считать универсальными. Source

Почему на Q3_K_M и Q2_K прирост заметнее

Логичное объяснение: чем грубее квантизация, тем чаще модель ошибается на промежуточных шагах и тем сильнее склонна к перепроверкам. Штраф убирает именно эти циклы, поэтому на Q3_K_M и Q2_K относительный прирост выше. Это согласуется с выводом Meta: ошибки переосмысления в квантизованных моделях снижаются вплоть до 58%.

Абсолютные значения важнее относительных. Q2_K с 24% точности всё ещё не годится для задач, где нужен правильный ответ. Прирост с 12% до 24% означает, что доля ошибок упала с 88% до 76%, и до рабочего качества тут далеко.

Ограничения эксперимента: почему нельзя слепо переносить результат

Выборка. 50 вопросов это 10% датасета MATH-500, причём датасет узкий: школьная и олимпиадная математика с однозначно проверяемым ответом. Повторных прогонов с разными сидами, доверительных интервалов и проверки на других моделях в тесте нет.

Масштаб. У Meta охват шире: 5 моделей, 3 метода квантизации, 5 бенчмарков, сокращение CoT на 12-23%. Здесь одна модель и один бенчмарк. Совпадение направления эффекта не означает совпадения величины.

Методология. Как именно считалась точность, как отбирались 50 вопросов, как измерялись reasoning-токены, в открытых материалах не расписано. Повторить тест один в один не получится, можно воспроизвести только схему.

Условия сборки. Все пять квантизаций взяты из одного репозитория, калибровка у них одинаковая. На сборках другого автора цифры могут отличаться.

Сравнивать свои результаты с чужими цифрами нужно осторожно: разные методики и стенды дают несопоставимые значения, эту ловушку разбирали на примере Prism-ML Bonsai 2.

Когда штраф за «wait» и «maybe» может навредить

  • Задачи с противопоставлениями. «However», «but», «although», «unless», «otherwise» вводят контрпримеры и ветвления. В доказательствах, разборе условий и юридических текстах штраф -2 бьёт по рабочим конструкциям.
  • Диалог и генерация текста. «Maybe» и «perhaps» там выражают уместную неуверенность, а «actually» часть нормального стиля.
  • Ошибки в списке ID. Если токены собраны на глаз, под штраф попадут фрагменты других слов, и качество просядет по причине, которую легко не заметить.
  • Срезанные рассуждения. Приём сокращает CoT на 11-19% в зависимости от квантизации, но не проверяет, были ли эти шаги лишними.

Как проверить метод на своей модели и стоит ли это делать

  1. Выберите модель и одну-две квантизации. Для старта Q4_K_M: разумный компромисс между качеством и размером.
  2. Соберите ID токенов для списка маркеров под свой токенизатор.
  3. Подготовьте набор из 50-100 задач с однозначно проверяемым ответом и зафиксируйте температуру и seed.
  4. Прогоните набор дважды: без bias и с --logit-bias -2 для собранных ID. Запишите точность, среднее число токенов генерации и время ответа.
  5. Сравните результаты и решите, оставлять ли флаги.

Готового набора задач под рукой может не быть. Тогда пригодится чужая методика оценки квантизаций, например тест через MMLU, HellaSwag и логические задачи, где сравнивают оригинальную модель с квантованными версиями и оценивают деградацию.

Сокращать reasoning-токены можно и по-другому, меняя саму модель: дообученные варианты Qwen снимают 30-50% длины рассуждений, но требуют отдельного файнтюна. Здесь же хватает набора флагов в командной строке.

Кому подходит метод, а кому нет

Подходит, если вы уже гоняете локальную модель в квантизации Q3-Q4 на ограниченной VRAM, хотите поднять точность без апгрейда железа и готовы один раз собрать список ID. Ожидаемый выигрыш: единицы процентных пунктов точности и ответы короче на 10-20%.

Не подходит, если задача критична по точности: штраф не компенсирует потери от срезанных битов, тут помогают Q8_0, BF16 или модель крупнее. Пройти мимо стоит и тогда, когда сценарий требует противопоставлений и честных оговорок, а времени на проверку эффекта на своём наборе задач нет.

Практический вывод: logit bias против маркеров переосмысления это дополнительный рычаг настройки, а не замена качественной квантизации. Приём не меняет веса, не требует обучения и легко откатывается: убрали флаги, вернули исходное поведение. Переносить конкретные цифры из одного теста на свою модель без проверки не стоит.

Подписаться на канал