fix(tokenizer): do not prepend a BOS token the tokenizer does not have - #1634
Merged
jlarson4 merged 1 commit intoAug 11, 2026
Merged
Conversation
get_input_with_manually_prepended_bos concatenated bos_token + input unconditionally, which is None + str for a tokenizer with no BOS token and raises TypeError naming neither the tokenizer nor the flag that caused it. With no BOS token there is nothing to prepend, so return the input unchanged. Reached when a tokenizer skips setup_tokenizer's bos_token = eos_token backfill, which is the initial-assignment branch at bridge_core.py:113, and tokenizer_prepends_bos is then corrected to False. That is the follow-up scoped out of TransformerLensOrg#1628; hardening it here unblocks the root-cause fix. The guard sits in the shared helper, so all three call sites are covered: transformer_bridge.py:717, HookedTransformer.py:850, remote_bridge.py:216. bos_token widens to Optional[str] because beartype rejects None against the old str annotation, so the runtime guard alone would still fail under test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Description
Follow-up to #1628. That issue fixed the removal side (
get_tokens_with_bos_removed, #1629) and deliberately left the prepend side alone, noting that the root-cause fix "needs the prepend path hardened first". This is that hardening.get_input_with_manually_prepended_bosconcatenatesbos_token + input. With no BOS token that isNone + str:With no BOS token there is nothing to prepend, so the helper now returns the input unchanged — the same shape of fix #1629 applied to the mirror-image helper.
How it is reached
Both normal paths are safe today.
setup_tokenizer(_hf_format.py:376) andHookedTransformer.set_tokenizer(HookedTransformer.py:801) each backfillbos_token = eos_token, so a booted model never handsNoneto this helper.The gap is the one #1628 identified. A bridge built via
build_bridge_from_module(tokenizer=None)and given a tokenizer afterwards takes the initial-assignment branch atbridge_core.py:113, soconfigure_tokenizer— and with it that backfill — never runs, andbos_tokenstaysNone. The staletokenizer_prepends_bos=Truecurrently keepsto_tokensout of the prepend branch. Correcting that flag, which is exactly what fixing #1628's root cause does, routesto_tokens(prepend_bos=True)straight into this helper.Before:
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'.After:
[[101, 19082, 1362, 102]]—[CLS] hello world [SEP], with[CLS]intact.So this unblocks the
bridge_core.py:113fix rather than competing with it.Scope
The guard lives in the shared helper, so all three call sites are covered in one place:
transformer_bridge.py:717,HookedTransformer.py:850, andremote_bridge.py:216. The HT-to-Bridge mirroring rule in AGENTS.md is satisfied by construction.bos_tokenis now typedOptional[str]. That part is load-bearing, not cosmetic: the repo's beartype instrumentation rejectsNoneagainst the oldstrannotation, so the runtime guard alone would still fail under test.Related to #1628 — this does not close it, since #1629 covers the removal side. I asked on the issue whether this warranted its own issue or a PR referencing that one; opening it here as the latter, happy to move it if a maintainer prefers.
Based on
dev-4.xto match #1628 and #1629. Happy to retarget todevif that is preferred — the only difference is thatOptionalis not yet imported intokenize_utils.pythere.Type of change
Checklist: