vllm - 💡(How to fix) Fix [Bug]: Thinking token budget not enforced with MTP speculative decoding (works without MTP) [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vllm-project/vllm#39573Fetched 2026-04-12 13:24:44
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Participants
Timeline (top)
labeled ×1

Code Example

vllm serve 'Qwen/Qwen3.5-35B-A3B-FP8' \
  --host 0.0.0.0 \
  --port 5001 \
  --reasoning-parser qwen3 \
  --reasoning-config '{"reasoning_start_str": "<think>", "reasoning_end_str": " Now formulate the final answer.</think>"}' \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_coder \
  --max-model-len 131072 \

---

import httpx
from openai import OpenAI

httpx_client = httpx.Client(verify=False, timeout=None)

client = OpenAI(
    base_url=base_url,
    api_key=api_key,
    http_client=httpx_client
)

completion = client.chat.completions.create(
    model="Qwen/Qwen3.5-35B-A3B-FP8",
    messages=[
        {"role": "system", "content": "Answer the user query"},
        {"role": "user", "content": "9.11 and 9.8, which is greater?"},
    ],
    extra_body={"thinking_token_budget": 50},
    temperature=0
)

print(completion.choices[0].message.reasoning)

---

Thinking Process:

1. Analyze the Request...
2. Identify the Numbers: Now formulate the final answer.

---

vllm serve 'Qwen/Qwen3.5-35B-A3B-FP8' \
  --host 0.0.0.0 \
  --port 5001 \
  --reasoning-parser qwen3 \
  --reasoning-config '{"reasoning_start_str": "<think>", "reasoning_end_str": " Now formulate the final answer.</think>"}' \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_coder \
  --max-model-len 131072 \
  --speculative-config.method mtp \
  --speculative-config.num_speculative_tokens 1 \
  --speculative-config.max_model_len 131072 \

---

import httpx
from openai import OpenAI

httpx_client = httpx.Client(verify=False, timeout=None)

client = OpenAI(
    base_url=base_url,
    api_key=api_key,
    http_client=httpx_client
)

completion = client.chat.completions.create(
    model="Qwen/Qwen3.5-35B-A3B-FP8",
    messages=[
        {"role": "system", "content": "Answer the user query"},
        {"role": "user", "content": "9.11 and 9.8, which is greater?"},
    ],
    extra_body={"thinking_token_budget": 50},
    temperature=0
)

print(completion.choices[0].message.reasoning)

---

Thinking Process:

1.  **Analyze the Request:** The user is asking to compare two numbers, 9.11 and 9.8, and determine which one is greater.

2.  **Identify the Numbers:**
    *   Number A: 9.11
    *   Number B: 9.8

3.  **Compare the Numbers:**
    *   Look at the whole number part (left of the decimal point): Both are 9.
    *   Look at the tenths place (first digit right of the decimal point):
        *   9.11 has a 1.
        *   9.8 has an 8.
    *   Compare the digits in the tenths place: 8 is greater than 1.
    *   Therefore, 9.8 is greater than 9.11.

4.  **Common Pitfall:** Sometimes people treat decimals like whole numbers (thinking 11 is greater than 8), but in decimal notation, place value matters. 9.8 is equivalent to 9.80. 9.80 > 9.11.

5.  **Formulate the Answer:** State clearly which number is greater and briefly explain why (comparing place values).

6.  **Final Output Construction:** "9.8 is greater than 9.11." (Maybe add a brief explanation for clarity).

    *   Draft: 9.8 is greater.
    *   Refinement: 9.8 is greater than 9.11. When comparing decimals, look at the tenths place. 8 is larger than 1.

7.  **Final Decision:** Keep it direct and helpful. "9.8 is greater." or "9.8 is greater than 9.11."

    Let's write: "9.8 is greater than 9.11."
    Explanation: 9.8 is the same as 9.80, and 80 hundredths is more than 11 hundredths.

    Wait, keep it simple.
    "9.8 is greater."

    Let's provide the answer clearly.
    "9.8 is greater than 9.11."

    Why?
    9.8 = 9.80
    9.11 = 9.11
    80 > 11.

    Okay, ready to generate response
RAW_BUFFERClick to expand / collapse

Your current environment

I am on docker vLLM API server version 0.19.0-cu130 GPU: 1 x B300 Model: Qwen/Qwen3.5-35B-A3B-FP8

🐛 Describe the bug

Thinking token budget (introduced in PR #20859) is not enforced when MTP speculative decoding is enabled, but works correctly when speculative decoding is disabled.

Key Observation: Without MTP → ✅ Thinking budget enforced With MTP → ❌ Thinking budget NOT enforced

Reproduction Case 1: Without Speculative Decoding (Works Correctly)

vllm serve 'Qwen/Qwen3.5-35B-A3B-FP8' \
  --host 0.0.0.0 \
  --port 5001 \
  --reasoning-parser qwen3 \
  --reasoning-config '{"reasoning_start_str": "<think>", "reasoning_end_str": " Now formulate the final answer.</think>"}' \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_coder \
  --max-model-len 131072 \

Python Script

import httpx
from openai import OpenAI

httpx_client = httpx.Client(verify=False, timeout=None)

client = OpenAI(
    base_url=base_url,
    api_key=api_key,
    http_client=httpx_client
)

completion = client.chat.completions.create(
    model="Qwen/Qwen3.5-35B-A3B-FP8",
    messages=[
        {"role": "system", "content": "Answer the user query"},
        {"role": "user", "content": "9.11 and 9.8, which is greater?"},
    ],
    extra_body={"thinking_token_budget": 50},
    temperature=0
)

print(completion.choices[0].message.reasoning)

Output (Trimmed)

Thinking Process:

1. Analyze the Request...
2. Identify the Numbers: Now formulate the final answer.

✅ Thinking stops early → budget respected

Case 2: With MTP Speculative Decoding (Fails)

vllm serve 'Qwen/Qwen3.5-35B-A3B-FP8' \
  --host 0.0.0.0 \
  --port 5001 \
  --reasoning-parser qwen3 \
  --reasoning-config '{"reasoning_start_str": "<think>", "reasoning_end_str": " Now formulate the final answer.</think>"}' \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_coder \
  --max-model-len 131072 \
  --speculative-config.method mtp \
  --speculative-config.num_speculative_tokens 1 \
  --speculative-config.max_model_len 131072 \

Python Script

import httpx
from openai import OpenAI

httpx_client = httpx.Client(verify=False, timeout=None)

client = OpenAI(
    base_url=base_url,
    api_key=api_key,
    http_client=httpx_client
)

completion = client.chat.completions.create(
    model="Qwen/Qwen3.5-35B-A3B-FP8",
    messages=[
        {"role": "system", "content": "Answer the user query"},
        {"role": "user", "content": "9.11 and 9.8, which is greater?"},
    ],
    extra_body={"thinking_token_budget": 50},
    temperature=0
)

print(completion.choices[0].message.reasoning)

Output

Thinking Process:

1.  **Analyze the Request:** The user is asking to compare two numbers, 9.11 and 9.8, and determine which one is greater.

2.  **Identify the Numbers:**
    *   Number A: 9.11
    *   Number B: 9.8

3.  **Compare the Numbers:**
    *   Look at the whole number part (left of the decimal point): Both are 9.
    *   Look at the tenths place (first digit right of the decimal point):
        *   9.11 has a 1.
        *   9.8 has an 8.
    *   Compare the digits in the tenths place: 8 is greater than 1.
    *   Therefore, 9.8 is greater than 9.11.

4.  **Common Pitfall:** Sometimes people treat decimals like whole numbers (thinking 11 is greater than 8), but in decimal notation, place value matters. 9.8 is equivalent to 9.80. 9.80 > 9.11.

5.  **Formulate the Answer:** State clearly which number is greater and briefly explain why (comparing place values).

6.  **Final Output Construction:** "9.8 is greater than 9.11." (Maybe add a brief explanation for clarity).

    *   Draft: 9.8 is greater.
    *   Refinement: 9.8 is greater than 9.11. When comparing decimals, look at the tenths place. 8 is larger than 1.

7.  **Final Decision:** Keep it direct and helpful. "9.8 is greater." or "9.8 is greater than 9.11."

    Let's write: "9.8 is greater than 9.11."
    Explanation: 9.8 is the same as 9.80, and 80 hundredths is more than 11 hundredths.

    Wait, keep it simple.
    "9.8 is greater."

    Let's provide the answer clearly.
    "9.8 is greater than 9.11."

    Why?
    9.8 = 9.80
    9.11 = 9.11
    80 > 11.

    Okay, ready to generate response

❌ Thinking continues far beyond configured budget

Expected Behavior:

  1. Thinking token budget should be strictly enforced
  2. Should cap reasoning tokens at configured limit
  3. Should work consistently across decoding modes (including MTP speculative decoding)

Actual Behavior:

  1. With MTP enabled, thinking budget is ignored
  2. Model generates significantly more reasoning tokens than configured
  3. Leads to increased latency and token usage

Before submitting a new issue...

  • Make sure you already searched for relevant issues, and asked the chatbot living at the bottom right corner of the documentation page, which can answer lots of frequently asked questions.

extent analysis

TL;DR

The thinking token budget is not enforced when MTP speculative decoding is enabled, causing excessive token generation and increased latency.

Guidance

  • Verify that the thinking_token_budget parameter is correctly set in the API request when MTP speculative decoding is enabled.
  • Check the server configuration to ensure that MTP speculative decoding is properly integrated with the thinking token budget enforcement mechanism.
  • Test the API with different decoding modes to confirm that the issue is specific to MTP speculative decoding.
  • Consider disabling MTP speculative decoding or adjusting the thinking_token_budget parameter to mitigate the issue.

Example

No code snippet is provided as the issue is related to the interaction between the API and the server configuration.

Notes

The root cause of the issue is likely related to the integration of MTP speculative decoding with the thinking token budget enforcement mechanism. Further investigation is needed to determine the exact cause and develop a permanent fix.

Recommendation

Apply a workaround by disabling MTP speculative decoding or adjusting the thinking_token_budget parameter to mitigate the issue, as the root cause is not immediately clear and may require further investigation.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING