You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] Reasoning tag removal fails when <think> is part of the input prompt #1453
When evaluating Qwen3.5-4B on a benchmark using exact-match accuracy, I observed unexpectedly low performance due to reasoning content not being removed from generated outputs.
The issue is in Pipeline._post_process_outputs, which removes reasoning content only when both <think> and </think> are present in the generated output.
For Qwen3.5-4B, the opening <think> tag is already included in the input prompt by the chat template, so only </think> appears in the generated output. As a result, reasoning content is not removed and affects exact-match accuracy.
Expected behavior
Reasoning removal should also handle cases where the opening tag is part of the input prompt.
A similar approach is implemented in Transformers' chat response parsing, which considers the input prefix when parsing generated responses.
I can confirm this, and the fix can stay entirely inside remove_reasoning_tags (src/lighteval/utils/utils.py). Once the paired tags have been stripped, an orphan closing tag that has no opening tag before it means the opening tag came from the prompt. Everything up to and including that closing tag is reasoning.
--- a/src/lighteval/utils/utils.py+++ b/src/lighteval/utils/utils.py
@@ def remove_reasoning_tags(text: str, tag_pairs: list[tuple[str, str]]) -> str:
else:
break
+ # The opening tag may have been part of the prompt (e.g. chat templates+ # that end with "<think>\n", like Qwen3.5), so the generation contains+ # only the closing tag. Drop everything up to that orphan closing tag.+ end = result.find(end_tag)+ if end != -1 and start_tag not in result[:end]:+ result = result[end + len(end_tag) :]+
return result
Behaviour before/after (I ran the existing docstring examples plus the new cases):
Okay, let me think...\n</think>\n\nB (the Qwen3.5 case)
unchanged
\n\nB
reasoning</think>A<think>more</think>
reasoning</think>A
A
Outputs without a closing tag are left as they are, so non-reasoning models aren't affected. Truncated reasoning (an opening tag but no closing one) is also unchanged, same as today. This is simpler than passing the prompt into post-processing the way Transformers' response parsing does, and covers the common chat-template case. Happy to send a PR with these as unit tests in tests/unit/utils/test_utils.py.
Activity
hamarshehmhmd commentedon Oct 27, 2026
I can confirm this, and the fix can stay entirely inside
remove_reasoning_tags(src/lighteval/utils/utils.py). Once the paired tags have been stripped, an orphan closing tag that has no opening tag before it means the opening tag came from the prompt. Everything up to and including that closing tag is reasoning.Behaviour before/after (I ran the existing docstring examples plus the new cases):
<think> Reasoning </think> AnswerAnswerAnswer<reasoning>Step 1</reasoning>Answer<reasoning>Step 2</reasoning>AnswerAnswerPlain answer<think> unfinished reasoning(truncated)Okay, let me think...\n</think>\n\nB(the Qwen3.5 case)\n\nBreasoning</think>A<think>more</think>reasoning</think>AAOutputs without a closing tag are left as they are, so non-reasoning models aren't affected. Truncated reasoning (an opening tag but no closing one) is also unchanged, same as today. This is simpler than passing the prompt into post-processing the way Transformers' response parsing does, and covers the common chat-template case. Happy to send a PR with these as unit tests in
tests/unit/utils/test_utils.py.