Skip to content

fix(server): a thinking request always leaves room to think - #845

Merged
davide221 merged 1 commit into
mainfrom
fix/thinking-room
Oct 14, 2026
Merged

davide221 merged 1 commit into
mainfrom
fix/thinking-room

Conversation

@davide221

@davide221 davide221 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

The reply reserve (hard_limit_reply_budget, 4096 on the Qwen cards) came off max_tokens in full. A request that asked for thinking with max_tokens 4096 or less got none: the phase-1 cap was 4096 − 4096 = 0, and the budget hook closed thinking on the first token. tool-eval-bench sends max_tokens: 4096, so reasoning_effort had no effect there, and neither did an Anthropic thinking budget with a small max_tokens.

Change

  • reply_reserve_within(reserve, max_tokens) in common/thinking_budget.h: the reserve takes at most half of max_tokens. With max_tokens 4096 on a 4096 card, the reply gets 2048 and thinking up to 2048.
  • One helper for the three places that size the envelope: apply_request_reasoning (the phase-1 cap), prepare_generation_inputs (the single-request path) and the scheduler's admission. Each subtracted the full reserve on its own before.
  • Requests with max_tokens above twice the reserve (8192 on a 4096 card) are unchanged.
  • docs/specs/thinking-budget.md §3.5, §4.4 and §5.3 describe the new reserve.

Measured

Qwen 3.8 27B UD-IQ4_XS on the R9700, with its DFlash2 drafter:

Request Before After
reasoning_effort: high, max_tokens: 4096 1 reasoning token (the forced </think>) 91 reasoning tokens; the model closed thinking itself
Messages API, thinking.budget_tokens: 2048, max_tokens: 3000 no thinking block thinking block, then the answer
tool-eval-bench --hardmode (97 scenarios, seed 42) with reasoning_effort: high 88 (no thinking ran) 91

The bench was measured on this change applied to 54132cac; after the rebase onto af91ead7 the unit tests were rerun.

Tests

  • test_reply_reserve_leaves_room_to_think: the helper, and the effort cap with max_tokens 1000, 150 and 100 on a 100-token reserve.
  • test_server_unit: 1002 passed, 0 failed (HIP build). The change is host C++ only.

🤖 Generated with Claude Code

View guided diff

The reply reserve (hard_limit_reply_budget, 4096 on the Qwen cards) came
off max_tokens in full. A request that asked for thinking with max_tokens
4096 or less got none: the phase-1 cap was 0 and the budget hook closed
thinking on the first token.

The reserve now takes at most half of max_tokens, through one helper,
reply_reserve_within(), used by the request parser, the single-request
path and the scheduler. Requests with max_tokens above twice the reserve
are unchanged.

@davide221 davide221 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review

No issues found. Checked for bugs and logic errors in the changed code.

Reviewed b02afd22 · 0 candidate issues checked, kept at ≥70% confidence · add the code-review label to review again

@davide221
davide221 merged commit af64ae9 into main Oct 14, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant