mirror of
https://github.com/deepseek-ai/DeepSeek-MoE.git
synced 2026-11-05 00:57:43 +00:00
[PR #54] fix: use the tokenizer's eos_token as the fine-tuning target terminator #51
Labels
No labels
pull-request
WIP
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
deepseek-ai/DeepSeek-MoE#51
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/deepseek-ai/DeepSeek-MoE/pull/54
Author: @PerryLink
Created: 9/17/2026
Status: 🔄 Open
Base:
main← Head:fix/eot-token-from-tokenizer📝 Commits (1)
0716312fix: use the tokenizer's eos_token as the fine-tuning target terminator📊 Changes
1 file changed (+13 additions, -4 deletions)
View changed files
📝
finetune/finetune.py(+13 -4)📄 Description
Summary
finetune/finetune.pyappends the hard-coded string"<|EOT|>"to every training target,but
<|EOT|>is not a token in the DeepSeekMoE tokenizer. This PR derives the terminatorfrom the loaded tokenizer's
eos_tokeninstead, with an optional--eot_tokenoverride.Fixes #37.
Problem
finetune/finetune.py:20(at66edeee) hard-codes:and
finetune/finetune.py:178builds the targets as:EOT_TOKENis used nowhere else in the file.That string is not in this model's vocabulary:
deepseek-ai/deepseek-moe-16b-base/-chat:eos_token=pad_token= the<|end of sentence|>special token (DeepSeek spells it with full-width vertical bars),added_tokens_decoderis empty andadditional_special_tokensis empty.tokenizer.jsonofdeepseek-moe-16b-basethe literal<|EOT|>does not occur at all;its 15
added_tokensare the two<|begin/end of sentence|>special tokens (again spelledwith full-width bars) plus 13 single-character tokens. So
<|EOT|>is not a token: it isshredded into ordinary sub-word/byte tokens.
Because
preprocess()keeps the target suffix inside the loss and the realeosneverappears in the labels, a model fine-tuned with this script never learns to end a turn.
That is exactly what was reported in #28, where the output degenerates into
<|EOT|>,<EOT>,<EOTOT>fragments repeated indefinitely; the resolution given there bya maintainer was to use the tokenizer's
eos_token.The constant is a leftover from
DeepSeek-Coder/finetune/finetune_deepseekcoder.py, whereline 14 is byte-identical (
EOT_TOKEN = "<|EOT|>") and line 117 is byte-identical to line 178here. It is correct for the Coder models (whose
eos_tokenreally is<|EOT|>) and wrongfor DeepSeekMoE.
Changes
EOT_TOKENconstant.train_tokenize_function(examples, tokenizer, eot_token=None)now resolves the terminatorat the point of use:
eot_token = tokenizer.eos_tokenwhen no override is given, and raisesa clear
ValueErrorif the tokenizer defines noeos_token(previously that case would havewritten the literal string
Noneinto the targets).--eot_tokento the existingDataArgumentsdataclass, threaded through the existingfn_kwargsplumbing.The trailing
\nbefore the terminator is kept: this script uses the Coder-style### Instruction:/### Response:prompt, which is also where the\ncomes from. Note thatthe official MoE chat template (
'Assistant: ' + content + eos_token) has no\nbefore theeos; if you would rather match that, it is a one-token change and I am happy to make it.Effect on existing users
eos, which is the point of the fix.--eot_token '<|EOT|>'.mapfingerprintshould change with the function body, but clearing is the safe route).
Test plan
python -m py_compile finetune/finetune.py- passes (Python 3.12).train_tokenize_functionwas exercised with a stubpreprocess:the model's
<|end of sentence|>token givesanswer\n<|end of sentence|>; a Coder-styletokenizer gives
answer\n<|EOT|>;--eot_tokenoverrides; noeosand no override raises.end-to-end "the model now stops" claim is not empirically verified here.
Notes
model_name_or_pathon line 39 isdeepseek-ai/deepseek-moe-16b, which does notresolve on the Hub (the existing repos are
-baseand-chat). Left untouched here to keepthis PR to one defect; flagging it since it may deserve its own fix.
AI assistance was used to prepare this patch (issue triage, evidence gathering, patch and test
drafting). The findings above were verified against the repository contents and the model
tokenizer files; please review as usual.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.