Do not hand the tokenizer loader an empty special token list on Apple - #22047
Open
shoumikhin wants to merge 2 commits into
Open
Do not hand the tokenizer loader an empty special token list on Apple#22047shoumikhin wants to merge 2 commits into
shoumikhin wants to merge 2 commits into
Conversation
ExecuTorchLLMTextRunner ends up holding an empty vector when the caller gives it no special tokens, and an empty vector is not the same as no vector. load_tokenizer takes it at face value and builds a Tiktoken whose BOS and EOS indices point past the end of an empty list, which aborts the process in the 1.4.0 prebuilts instead of returning an error. Pass nothing when the list is empty so the tokenizer uses its own defaults, and copy the list instead of moving it so a retry after a failed load still has it.
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/22047
Note: Links to docs will display an error until the docs builds have been completed. ✅ No FailuresAs of commit f8e2f17 with merge base fbd4bbf ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a
|
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.
Part of #21805.
The Apple frameworks are built from the
extension/llm/tokenizerssubmodulepin. The tokenizers half of this bug is meta-pytorch/tokenizers#210, and it
reaches iOS users only once that pin moves forward. This PR does not move it.
Problem
ExecuTorchLLMTextRunner's two argument initializer passes@[]for specialtokens, and the three argument one accepts whatever array the caller gives it,
including an empty one. In both of those cases the runner ends up holding an
empty
std::vector<std::string>and hands that toload_tokenizer.An empty vector is not the same thing as no vector.
load_tokenizertakes it atface value and builds a
Tiktokenwhose BOS index 0 and EOS index 1 point pastthe end of an empty list. In the 1.4.0 prebuilts that reached an
abort()inthe
Tiktokenconstructor, so the app died with signal 6 rather than returningan error. It happens whenever the HuggingFace loader fails first and the chain
falls through to Tiktoken, which is the path a Qwen style
tokenizer.jsontakestoday.
There is a second, quieter bug in the same lines. The special tokens were moved
into
load_tokenizer, which leaves the runner's own pointer null, not empty. Acaller that retried
loadafter a failure therefore took the branch that means"no list was given", and
Tiktokenfilled in its own 256 built in Llama 3special tokens. The retry looks like it succeeded while quietly producing token
ids from the wrong list.
Solution
Pass nothing when the list is empty, so the tokenizer falls back to its own
defaults, and copy the list instead of moving it so a retry still has it.
This covers the empty case only, which is the one the runner itself creates. An
empty array means the caller never specified a list, because the two argument
initializer manufactures
@[]. A caller that passes a list with fewer than twoentries is stating a list that cannot work, since this API fixes the BOS index at
0 and the EOS index at 1. That stays an error, and after
meta-pytorch/tokenizers#210 it is reported as an error instead of killing the
process.
Test plan
Copied
load_tokenizerinto a small C++ program and called it three waysagainst a Tiktoken model file, on Linux x86_64, built against
meta-pytorch/tokenizers#210:
bos index 0 and eos index 1 must both be below the special token count 0, the chain returns null, no abortCI compiles the changed file clean for iOS device, iOS simulator and macOS, in
the
apple (ios),apple (ios-simulator)andapple (macos)builds. The onewarning reported against it comes from a header it includes and shows up on the
unchanged files in the same target too.
Not tested: there is no run on a device, and no automated test. The repository
has no host runnable harness that exercises this binding, and the existing Swift
tests cover a successful load, not this fall through.