pad_token無しモデルでfinish_reasonが常にlengthになる問題を修正 - #296
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
kiakiraki
marked this pull request as ready for review
July 19, 2026 02:58
junya-takayama
approved these changes
Jul 23, 2026
junya-takayama
left a comment
Collaborator
There was a problem hiding this comment.
LGTM!ありがとうございます!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
問題
HuggingFaceLMで pad_token を持たないトークナイザ(GPT-2系・Llama系など)を使うと、tokenize_text_for_lm_prefixがpad_token = eos_tokenにフォールバックします。このとき_batch_complete_textの後処理に2つの問題がありました。t != pad_token_idで全 pad を除去するため、pad==eos の場合は生成を止めた本物の EOS トークンまで除去される。その結果、後段のテキストレベル stop 検索が絶対に成立せず、EOS で正常終了してもfinish_reasonが常に"length"になる。FinishReasonCountは全生成系セットアップに自動付与されるため、該当モデルではfinish_reason_ratio-*メトリクスがそのまま間違う。decode_for_lm_continuationの境界計算が狂って出力テキストが破損し得る(SentencePiece 系では先頭スペースの欠落として顕在化)。修正内容
finish_reasonの判定をテキストレベルからトークンレベルに移しました。output_tensor中で最初にstop_token_idsのトークンが現れる位置を探し、見つかればfinish_reason="stop"としてそれ以降(stop トークン+パディング)を破棄。generate の仕様上、生成領域で stop トークンが現れるのは生成停止位置だけなので、pad==eos でも最初の出現位置は必ず本物の停止位置です。見つからなければ従来どおり"length"(専用 pad モデル向けに pad 除去フィルタは防御として維持)attention_maskベースに変更し、プロンプト中の本物の EOS を保持_get_stop_token_idsが token id 化しないため、引き続き必要)専用 pad トークンを持つモデルの挙動は完全に不変です。テキスト出力も全ケースで不変で、変わるのは pad 無しモデルの
finish_reasonのみです。テスト
model.generateをスタブ化し、既知のテンソル(生成トークン+EOS+パディング)を返させて後処理を決定的に検証する方式で4件追加しました。トークナイザは既存テストで使用実績のあるtokyotech-llm/Swallow-7b-instruct-hf(pad_token 無し)に統一しています。モデル本体はスタブなので重みのダウンロードは発生しません。"stop"'length' == 'stop'で fail"length"'です。' == ' です。'で failtests/core/language_model/test_hf_lm.py全体で 76 passed、既存テストの回帰なし。ruff check / format パス。相談: 実生成でのエンドツーエンド検証について
本 PR のテストは
model.generateをスタブ化した後処理の検証のみです。実生成でこのバグを再現するには「pad_token を持たない実モデル」が必要ですが、既存テストで実ロードしているモデル(sbintuitions/tiny-lm系)は専用<pad>トークンを持つため再現できません(まさにそれが原因で本バグは既存テストをすり抜けていました)。実生成テストを追加するなら
sshleifer/tiny-gpt2のような外部の極小 pad 無しモデルの導入が必要になります。外部モデルをテストに追加するか、スタブ検証のみで許容するか、ご判断をお願いします。🤖 Generated with Claude Code