Skip to content

[#17020][fix] DeepSeek-V4: honor thinking_budget in apply_chat_template - #17035

Draft
thorjohnsen wants to merge 1 commit into
NVIDIA:mainfrom
thorjohnsen:fix/17020-deepseek-v4-thinking-budget
Draft

[#17020][fix] DeepSeek-V4: honor thinking_budget in apply_chat_template#17035
thorjohnsen wants to merge 1 commit into
NVIDIA:mainfrom
thorjohnsen:fix/17020-deepseek-v4-thinking-budget

Conversation

@thorjohnsen

Copy link
Copy Markdown
Collaborator

Description

DeepseekV4Tokenizer.apply_chat_template reads only thinking / enable_thinking. Every kwarg is fetched with kwargs.get, so an unrecognized key is silently dropped — and thinking_budget is exactly such a key.

That matters because trtllm-eval aime25 and aime26 default --chat_template_kwargs to {"thinking_budget": 32768} (lm_eval.py:1513 / :1630). DeepSeek-V4 ships no Jinja chat template — the checkpoint has no chat_template in tokenizer_config.json — so the hand-written renderer at tokenizer/deepseek_v4/tokenizer.py is the only thing that could honor the key. Today it does not, thinking falls back to False, and the prompt ends <|Assistant|></think> with the reasoning block pre-closed. The default output is byte-identical to explicitly passing {"thinking": false}.

Nothing in the logs or the results indicates this happened. The run completes successfully and reports a plausible-looking score.

Measured on DeepSeek-V4-Flash, AIME 2025, 4xGB300, TP4/EP4, greedy, everything else identical:

--chat_template_kwargs exact_match
'{"thinking_budget": 32768}' (current default) 43.33 (13/30) ±9.20
'{"thinking": true}' 86.67 (26/30) ±6.31

This is genuine capability loss rather than a scoring artifact: 29/30 non-thinking responses did contain a \boxed{}, and 15 of the 17 failures boxed a confidently wrong value.

The change

Thinking resolution moves into one helper. thinking / enable_thinking win whenever the caller passes either, so behavior is unchanged for every caller using the native keys. Only when neither is present does thinking_budget decide: a positive budget means "think", 0 disables it. That is the semantic the CLI help text already documents ("set to 0 to disable thinking").

Reported as #17020. The companion suggestion in that issue — warning on unrecognized chat_template_kwargs keys — is deliberately left out of this PR to keep it to a single concern; happy to follow up if wanted.

Test Coverage

tests/unittest/llmapi/test_deepseek_v4_tokenizer.py, three new cases:

  • test_deepseek_v4_chat_template_supports_thinking_budget — a positive budget opens <think>
  • test_deepseek_v4_chat_template_thinking_budget_zero_disables_thinking0 keeps the block pre-closed
  • test_deepseek_v4_chat_template_native_thinking_key_wins_over_budget — explicit thinking=False beats a positive budget, pinning the precedence rule

The existing cases in that file cover the unchanged thinking / enable_thinking / reasoning_effort paths.

PR Checklist

  • Please check this after reviewing the above items as appropriate for this PR.

…template

DeepseekV4Tokenizer.apply_chat_template read only `thinking` /
`enable_thinking`. Every kwarg is fetched with `kwargs.get`, so the
`thinking_budget` key was silently dropped and the request fell back to
non-thinking chat mode.

This matters because `trtllm-eval aime25` and `aime26` default
`--chat_template_kwargs` to `{"thinking_budget": 32768}`, and DeepSeek-V4
ships no Jinja chat template (the checkpoint has no `chat_template` in
tokenizer_config.json), so the hand-written renderer is the only thing that
can honor the key. The result is a run that completes successfully and
reports a plausible-looking score with thinking disabled.

Resolve thinking in one place: `thinking` / `enable_thinking` win whenever
either is passed, so existing behavior is unchanged for callers that use the
native keys; otherwise `thinking_budget` decides, with a positive budget
meaning "think" and 0 disabling it. That matches the semantic the CLI help
text already documents ("set to 0 to disable thinking").

Fixes NVIDIA#17020

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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