Skip to page content
SAVRN
Search Plan a project

Dataset

overthinking-logit-bias

by UEDA Naoaki na0x2c6/overthinking-logit-bias

Logit bias lists and a script to apply the overthinking penalty of Lotfi et al., "Quantized Reasoning Models Think They Need to Think Longer, but They Do Not" (arXiv:2606.00206) with llama.cpp's llama-server.

Rows—
Configurations—
Size266.2 KB
Licenseapache-2.0
AccessPublicly accessible
Monthly Downloads22

Dataset Card

By UEDA Naoaki, published under apache-2.0, revision 911574442885.

Overthinking penalty logit bias for llama.cpp

Logit bias lists and a script to apply the overthinking penalty of Lotfi et al., "Quantized Reasoning Models Think They Need to Think Longer, but They Do Not" (arXiv:2606.00206) with llama.cpp's llama-server.

The method subtracts a fixed λ from the logits of 50 overthinking markers (Appendix C, Table 8: " Wait", " But", " Alternatively", " perhaps", ...) at every decoding step. It needs no extra forward pass, so llama.cpp's logit bias is all it takes.

For Ornith-1.5 and models built from it (e.g. Tiel-Coder), use the paragraph-initial list (--initial, bias/ornith-1.5-35b-a3b/initial-lambda-*) rather than the paper's list. These models open a new line of reasoning at the start of a paragraph ("\n\nWait,", "\n\nActually,"), where the word has no leading space and is a different token from the paper's " Wait". The paper's list barely shortened Ornith-1.5's reasoning (−6% tokens); the paragraph-initial list at λ = 4 cut it by 34% on MATH-500 level 3–5 with all answers still correct, and on hard coding-agent tasks it let the model get past the reasoning cut-off (see Verification and REPORT.md). This variant is not in the paper.

Files

Path Content
make_logit_bias.py Builds the list for any GGUF (Python standard library only)
REPORT.md How the lists were verified, on Ornith-1.5 and Tiel-Coder
tasks/ Texts and hidden tests of the three hard coding tasks used in the report
bias/qwen3.8-27b/lambda-2.0.json λ = 2.0 as [[token_id, bias], ...], for the logit_bias request field
bias/qwen3.8-27b/lambda-2.0.args The same as llama-server options (-l ID-BIAS ...)
bias/ornith-1.5-35b-a3b/lambda-2.0.{json,args} The same for Ornith-1.5-35B-A3B
bias/*/initial-lambda-4.0.{json,args} Paragraph-initial markers (--initial), λ = 4.0: needed by Ornith-1.5 Q3_K_L
bias/*/initial-lambda-2.0.{json,args} The same at λ = 2.0: enough for Tiel-Coder UD-IQ4_XS, and faster

Token IDs depend on the vocabulary, not on the model weights or the quantization. The Qwen3.8-27B family, the Qwen3.5-35B-A3B family and the Ornith family derived from them share one tokenizer (248,320 tokens, sha256:f307bf31f9c6130c as printed by the script), so the lists here are identical and fit any of these models.

For any other model, build the list yourself (below); it takes a second. 49 of the 50 markers are single tokens in this vocabulary; " recheck" is two tokens and is skipped.

1. Build the list

# Local GGUF (the first shard of a split model)
python3 make_logit_bias.py model.gguf -p 2.0 -o bias.json

# GGUF on the Hub: only the header is downloaded (a few MB)
python3 make_logit_bias.py hf://OWNER/REPO/model-Q4_K_M.gguf -p 2.0 -o bias.json

# llama-server options instead of JSON
python3 make_logit_bias.py model.gguf -p 2.0 -f cli

# Paragraph-initial markers instead of the paper's list
python3 make_logit_bias.py model.gguf --initial -p 4.0 -o bias.json

-p is λ (> 0). The paper sweeps 0.5–4.0 and reports the best λ per configuration; there is no single recommended value. The script prints the token ID of each marker and the vocabulary hash to stderr. Set HF_TOKEN for gated repos. Supported tokenizers: byte-level BPE (gpt2, e.g. Qwen, Llama 3) and SentencePiece (llama).

Paragraph-initial markers (--initial)

--initial replaces the paper's 50 leading-space markers with 10 capitalized markers spelled without a leading space, the form a word takes at the start of a paragraph:

Wait, Hmm, Actually, But, However, Alternatively, Instead, Or, Maybe, Perhaps

These are the words Ornith-1.5 opens its reasoning branches with, plus the capitalized hedges of the paper's list. "Actually" is not in the paper (only " actually" is), but it is the most frequent opener in Ornith-1.5 (100 times over 15 MATH problems without bias); in a sample of 10, 7 started a revision and 3 a neutral rephrasing. Lower-case forms without a space are left out: they are mostly word pieces ("thres|hold", "Iterat|or"). An --also-no-space option, which adds the no-space form of all 50 markers (83 tokens), shortens the reasoning about as much but penalizes such word pieces as well.

2. Use it with llama-server

Per request

llama-server accepts logit_bias as an array of [token_id, bias] pairs on /completion and the OpenAI-compatible /v1/chat/completions:

jq -n --slurpfile lb bias.json '{
  messages: [{role: "user", content: "How many primes are below 100?"}],
  logit_bias: $lb[0]
}' | curl -s http://127.0.0.1:8080/v1/chat/completions \
       -H 'Content-Type: application/json' -d @-

With the OpenAI Python client:

import json
from openai import OpenAI

client = OpenAI(base_url="http://127.0.0.1:8080/v1", api_key="none")
bias = json.load(open("bias.json"))
resp = client.chat.completions.create(
    model="local",
    messages=[{"role": "user", "content": "How many primes are below 100?"}],
    extra_body={"logit_bias": bias},  # a list of pairs, so pass it in extra_body
)

Many agents and clients have an "extra body" setting where the same {"logit_bias": [...]} can go.

Server-wide

llama-server -m model.gguf $(cat bias/qwen3.8-27b/lambda-2.0.args)

Caveats

  • A request's logit_bias replaces the server's -l list rather than adding to it.
  • --models-preset (INI) cannot hold the list: a preset keeps one value per key and --logit-bias takes one token, so only the last entry would apply. Use the per-request form with router mode.
  • The penalty applies to the whole output, not only to the reasoning: the answer, code and comments also see fewer " or", " but", " error", " could", and so on. Only the leading-space forms are penalized, so e.g. error at the start of a line or after ( is not affected. With --initial it is the other way round: only the no-space forms (start of a line, after (, ", **, ...) are penalized, so a sentence or a bullet that starts with "But" or "However" becomes less likely, while the same words mid-sentence are unaffected. Identifiers such as Or or Maybe in code are affected too.
  • The reasoning gets shorter on average, but single runs vary a lot, and a run does not always finish sooner (see REPORT.md).
  • Penalizing one form moves the hesitation to the others: with --initial alone, Tiel-Coder hesitated mid-sentence instead; without "Actually", Ornith opened its paragraphs with "Actually" instead.
  • The IDs are only valid for the vocabulary they were built from. A list for another vocabulary silently penalizes unrelated tokens.

Verification

See REPORT.md for the setup and all results. In short, on Ornith-1.5-35B-A3B and Tiel-Coder-35B-A3B:

  • The token IDs from the GGUF match llama-server's /tokenize, and the bias lowers the marker probabilities as expected.
  • MATH-500 (15 problems, levels 3–5, Ornith): the paper's list at λ = 2 cut the tokens by 6%, --initial at λ = 4 by 34%, all answers still correct.
  • Coding agent (pi, three hard tasks): without the penalty, the first long reply often reasoned until the 16384-token cut-off and nothing was written. With --initial, the agent got to write and test code that passed the hidden tests: Ornith-1.5 Q3_K_L needed λ = 4, Tiel-Coder UD-IQ4_XS managed with λ = 2. The paper's list, alone or together with --initial, did not get either model past the cut-off on the hardest task.
  • Removing "Actually" from the list moved the hesitation to "Actually".
  • The penalty does not always save time, and single runs vary a lot.
  • In progress: the same tasks on lower quantizations of Ornith (Q2_K_L, IQ2_XXS), to see whether the λ needed depends on the quantization.

Evaluate on your own tasks before relying on the penalty.

Citation

@misc{lotfi2026quantized,
  title         = {Quantized Reasoning Models Think They Need to Think Longer, but They Do Not},
  author        = {Lotfi, Sanae and Kirichenko, Polina and Li, Steven and Liu, Zechun},
  year          = {2026},
  eprint        = {2606.00206},
  archivePrefix = {arXiv},
  url           = {https://arxiv.org/abs/2606.00206}
}

The marker list is taken from Table 8 of the paper. This repository is not affiliated with the authors.

License

The script and the lists are released under the Apache License 2.0 (see LICENSE).

Details

Repository
na0x2c6/overthinking-logit-bias
Publisher
UEDA Naoaki
Task category
Not stated by the source
Tags
llama.cpp, gguf, logit-bias
Size category
Not stated by the source
Languages
Not stated by the source
Revision
911574442885f5221b062eee86fe04c2874f6e82
Last updated
2026-10-12

Files

28 files, 266.2 KB in total.

Data7 files · 210.8 KB
Documentation5 files · 34.0 KB
Other15 files · 18.9 KB
Repository1 file · 2.5 KB
Every file
FileTypeSizeSHA-256
bias/ornith-1.5-35b-a3b/initial-lambda-2.0.jsonData149 B—
bias/ornith-1.5-35b-a3b/initial-lambda-4.0.jsonData149 B—
bias/ornith-1.5-35b-a3b/lambda-2.0.jsonData707 B—
bias/qwen3.8-27b/initial-lambda-2.0.jsonData149 B—
bias/qwen3.8-27b/initial-lambda-4.0.jsonData149 B—
bias/qwen3.8-27b/lambda-2.0.jsonData707 B—
tasks/semver/hidden/semver_cases.jsonData208.7 KB—
LICENSEDocumentation11.4 KB—
README.mdDocumentation8.8 KB—
REPORT.mdDocumentation11.6 KB—
tasks/README.mdDocumentation1.4 KB—
tasks/calc/work/README.mdDocumentation863 B—
bias/ornith-1.5-35b-a3b/initial-lambda-2.0.argsOther108 B—
bias/ornith-1.5-35b-a3b/initial-lambda-4.0.argsOther108 B—
bias/ornith-1.5-35b-a3b/lambda-2.0.argsOther510 B—
bias/qwen3.8-27b/initial-lambda-2.0.argsOther108 B—
bias/qwen3.8-27b/initial-lambda-4.0.argsOther108 B—
bias/qwen3.8-27b/lambda-2.0.argsOther510 B—
make_logit_bias.pyOther8.5 KB—
tasks/calc/hidden/test_hidden.pyOther1.1 KB—
tasks/isoweek/hidden/test_hidden.pyOther1.5 KB—
tasks/isoweek/work/isoweek.pyOther454 B—
tasks/isoweek/work/test_isoweek.pyOther101 B—
tasks/semver/hidden/gen_cases.jsOther1.9 KB—
tasks/semver/hidden/test_hidden.pyOther924 B—
tasks/semver/work/semverrange.pyOther2.8 KB—
tasks/semver/work/test_semverrange.pyOther139 B—
.gitattributesRepository2.5 KB—

License and Download

License
apache-2.0
Access
No access gate
Download from UEDA Naoaki

Released by UEDA Naoaki through its official repository on Hugging Face. Read the license.