Skip to content

fix: match qwen3-thinking double-newline in train_on_responses_only response pattern - #6926

Merged
Etherll merged 3 commits into
unslothai:mainfrom
InfoSage05:fix/6919-qwen3-thinking-response-pattern
Jul 7, 2026
Merged

Etherll merged 3 commits into
unslothai:mainfrom
InfoSage05:fix/6919-qwen3-thinking-response-pattern

Conversation

@InfoSage05

Copy link
Copy Markdown
Contributor

What broke

The Qwen3-thinking chat template produces <think>\n\n (double newline) after the <think> tag. The tokenizer merges \n\n into token ID 271, while \n alone is token ID 198.

train_on_responses_only in the Studio was searching for <think>\n (token 198) as the response start pattern. Since the actual tokenized text contains token 271 at that position, the pattern never matched. Every training sample had ALL tokens masked as -100, causing 100% of samples to be dropped.

Minimal repro

from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("unsloth/Qwen3.6-27B", trust_remote_code=True)
messages = [{"role": "user", "content": "x"}, {"role": "assistant", "content": "{}"}]
text = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=False)
ids = tok(text, add_special_tokens=False).input_ids

print(repr(text))
# '<|im_start|>user\nx<|im_end|>\n<|im_start|>assistant\n<think>\n\n</think>\n\n{}<|im_end|>\n'

print(ids)
# [248045, 846, 198, 87, 248046, 198, 248045, 74455, 198, 248068, 271, ...]
#                                                                     ^^^
#                                             token 271 = \n\n, not token 198 = \n

Fix

One-character change in model_mappings.py that is to add the missing \n to match the actual template output:

- "response": "<|im_start|>assistant\n<think>\n",
+ "response": "<|im_start|>assistant\n<think>\n\n",

File: studio/backend/utils/datasets/model_mappings.py:490
Branch: fix/6919-qwen3-thinking-response-pattern

Fixes #6919

…ttern

The Qwen3-thinking chat template generates `<think>\n\n` (double newline)
after the think tag, but `train_on_responses_only` was looking for
`<think>\n` (single newline).

`\n\n` is token 271 while `\n` is token 198 -- different tokens, so the
pattern match in `train_on_responses_only` fails, masking ALL tokens and
dropping 100% of training samples.

Update the response pattern from `<think>\n` to `<think>\n\n` to match
what the actual qwen3-thinking template generates.

Fixes unslothai#6919
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@alkinun

alkinun commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

could repro this on my end too @Etherll

@compumike

Copy link
Copy Markdown

Just added a comment here #6919 (comment) that this approach (matching double newline) breaks things if reasoning_content is provided.

I think matching "<|im_start|>assistant\n<think>" (with no trailing newline) is safer.

It also might just be easiest to set force_match = False because it looks like this behavior is already handled to some degree in the train_on_responses_only(..., force_match = False) branch of code!

@Etherll

Etherll commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Just added a comment here #6919 (comment) that this approach (matching double newline) breaks things if reasoning_content is provided.

I think matching "<|im_start|>assistant\n<think>" (with no trailing newline) is safer.

It also might just be easiest to set force_match = False because it looks like this behavior is already handled to some degree in the train_on_responses_only(..., force_match = False) branch of code!

I agree <|im_start|>assistant\n<think> would be better

@Etherll Etherll left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM!

@Etherll
Etherll merged commit 304b8ec into unslothai:main Jul 7, 2026
33 of 34 checks passed
alkinun pushed a commit to alkinun/unsloth that referenced this pull request Jul 8, 2026
…esponse pattern (unslothai#6926)

* fix: match qwen3-thinking chat template double-newline in response pattern

The Qwen3-thinking chat template generates `<think>\n\n` (double newline)
after the think tag, but `train_on_responses_only` was looking for
`<think>\n` (single newline).

`\n\n` is token 271 while `\n` is token 198 -- different tokens, so the
pattern match in `train_on_responses_only` fails, masking ALL tokens and
dropping 100% of training samples.

Update the response pattern from `<think>\n` to `<think>\n\n` to match
what the actual qwen3-thinking template generates.

Fixes unslothai#6919

* fix qwen3 thinking response marker

---------

Co-authored-by: Ayushman Paul <ayushman@HP>
Co-authored-by: Etherll <61019402+Etherll@users.noreply.github.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.

train_on_responses_only breaks with qwen3-thinking template because \n\n is a different token than \n

4 participants