[Bugfix][Frontend] Count reasoning tokens for the Muse-Glimmer parser - #54091
meghana-madhyastha wants to merge 1 commit into
Conversation
The muse_glimmer reasoning parser inherited the base count_reasoning_tokens() that returns 0, so usage.completion_tokens_details.reasoning_tokens was always 0. Classify the decoded output with the parser's own logic, including the turn re-open after tool calls, and count the reasoning text. Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Meghana Madhyastha <meghana.madhyastha@parasail.io>
|
👋 Hi! Thank you for contributing to the vLLM project. 💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment Once the PR is approved or has the If you have any questions, please reach out to us on Slack at https://slack.vllm.ai. Agent GuidelinesIMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban. 🚀 |
|
I think that #54238 is better approach :) |
MuseGlimmerReasoningParser inherited the base count_reasoning_tokens() that returns 0, so usage.completion_tokens_details.reasoning_tokens was always 0 for --reasoning-parser muse_glimmer. The ATEM framing markers are not guaranteed to be single vocab tokens (e.g. " to=self" is two tokens), so tokens cannot be classified by id. Instead, decode each token once (cached per request), record its character offset, locate to=self bodies in the decoded text, and count the tokens starting inside those spans with bisect. This counts the original tokens exactly rather than re-encoding the reasoning text. The body-end rule (<|eom|> / <|eot|> / next channel header / EOF) is factored into _body_end() and shared with _classify_bodies(), so the streamed reasoning text and the reported count cut bodies identically. Related: vllm-project#54091 takes the decode -> classify -> re-encode approach for the same bug; this variant is exact at span boundaries and ~12x cheaper per call (247us vs 2984us at 4k reasoning tokens with the real tokenizer), which matters because chat streaming re-counts the full token list on every delta. Signed-off-by: Donghee Na <donghee.na92@gmail.com>
The muse_glimmer reasoning parser inherited the base count_reasoning_tokens() that returns 0, so usage.completion_tokens_details.reasoning_tokens was always 0. Classify the decoded output with the parser's own logic, including the turn re-open after tool calls, and count the reasoning text.
Purpose
With
--reasoning-parser muse_glimmer, chat completions always reportreasoning_tokens: 0inusage.completion_tokens_details, because the parser inherits the basecount_reasoning_tokens()that returns 0. Clients that rely on the count (OpenRouter's reasoning checks, billing) see no reasoning even when the model produced a long reasoning body.This implements
count_reasoning_tokens()for the Muse-Glimmer parser: decode the generated ids, classify the bodies with the parser's existing logic, and re-encode the reasoning text to count it. Classification is done without anchoring to the current assistant turn, because after a tool call the model re-opens the turn (<|eom|><|start|>assistant to=user<|message|>) and a turn-anchored scan would drop the reasoning emitted before it.Note: developed with AI assistance (Claude); the code and tests were reviewed and validated end-to-end by the author.
Test Plan
New unit tests in
tests/reasoning/test_muse_glimmer_count_reasoning_tokens.py(reasoning only, reasoning + content, no reasoning, tool-call turn re-open, empty input).Test Result
Before:
reasoning_tokens: 0for every request.After: e.g.
reasoning_tokens: 43for a request with an 83-character reasoning body,0when the model emits none; tool-call turns count the reasoning emitted before the re-open. Unit tests pass.Essential Elements of an Effective PR Description Checklist
supported_models.mdandexamplesfor a new model.