Repository navigation
Fix loading HF tokenizers with no-op normalizer and non-tiling Split regexes - #225
Merged
larryliu0820 merged 1 commit intoOct 19, 2026
Conversation
…it regexes
Two fixes for tokenizer.json files that are valid per the HuggingFace
tokenizers spec but failed to load or encode incorrectly:
1. NormalizerConfig::create() rejected an empty Sequence normalizer
({"type": "Sequence", "normalizers": []}). An empty list is valid
and acts as a no-op, matching the Rust implementation. Spark-X2.5
tokenizer.json ships this form and failed to load.
2. RegexPreTokenizer treated every Regex-pattern Split as "return the
matches", which is only correct for invert=true or regexes that tile
the input (GPT-2 / llama3 style). Per the HF spec, a Split with
invert=false uses the matches as delimiters: non-matching text must
be kept and the behavior field applies. Without this, patterns that
do not tile the input (e.g. Spark-X2.5 digit isolation \p{N}{1,3}
with behavior=Isolated) silently dropped all non-matching text, so
encode() returned zero tokens for ordinary prompts. Now a Regex
pattern with an explicit behavior and invert=false uses delimiter
semantics; invert=true and behavior-less configs keep the previous
behavior.
Verified end-to-end with the real XHToken/Spark-X2.5-1.7B tokenizer.json:
load OK, encode("Once upon a time,") -> [19327 6420 259 1279 25],
decode round-trips exactly.
This PR was authored with AI assistance using Claude Code.
dongjiang1989
added a commit
to XHToken/executorch
that referenced
this pull request
Oct 15, 2026
This commit adds CI test support for Spark-X2.5-1.7B and Spark-X2.5-4B models to the ExecuTorch test infrastructure. Changes: - Added spark_x2_5_1_7b and spark_x2_5_4b to test_torchao_huggingface_checkpoints.sh - Added both models to CI test matrix in trunk.yml - Configured XNNPACK (x86_64) and TorchAO (ARM64) backend testing - Use --local-dir for hf download to avoid read-only /mnt/hf_cache issues - convert_weights now rewrites the no-op normalizer in Spark-X2.5 tokenizer.json (empty Sequence, rejected by older revisions of the C++ HF tokenizer) to null, which is semantically identical, so llama_main can load it. The root cause is also fixed upstream in meta-pytorch/tokenizers#225; the submodule pin will be bumped once that lands. The Spark-X2.5 model infrastructure already exists in the codebase. This commit completes the integration by adding automated CI testing. Parts of this commit were authored with AI assistance using Claude Code. Signed-off-by: dongjiang <dongjiang1989@126.com>
Contributor
Author
|
cc @larryliu0820 Can you review this PR? Thx |
Contributor
Author
|
Thanks @larryliu0820 |
dongjiang1989
added a commit
to XHToken/executorch
that referenced
this pull request
Oct 23, 2026
This commit adds CI test support for Spark-X2.5-1.7B and Spark-X2.5-4B models to the ExecuTorch test infrastructure. Changes: - Added spark_x2_5_1_7b and spark_x2_5_4b to test_torchao_huggingface_checkpoints.sh - Added both models to CI test matrix in trunk.yml - Configured XNNPACK (x86_64) and TorchAO (ARM64) backend testing - Use --local-dir for hf download to avoid read-only /mnt/hf_cache issues - convert_weights now rewrites the no-op normalizer in Spark-X2.5 tokenizer.json (empty Sequence, rejected by older revisions of the C++ HF tokenizer) to null, which is semantically identical, so llama_main can load it. The root cause is also fixed upstream in meta-pytorch/tokenizers#225; the submodule pin will be bumped once that lands. The Spark-X2.5 model infrastructure already exists in the codebase. This commit completes the integration by adding automated CI testing. Parts of this commit were authored with AI assistance using Claude Code. Signed-off-by: dongjiang <dongjiang1989@126.com>
dongjiang1989
added a commit
to XHToken/executorch
that referenced
this pull request
Oct 23, 2026
This commit adds CI test support for Spark-X2.5-1.7B and Spark-X2.5-4B models to the ExecuTorch test infrastructure. Changes: - Added spark_x2_5_1_7b and spark_x2_5_4b to test_torchao_huggingface_checkpoints.sh - Added both models to CI test matrix in trunk.yml - Configured XNNPACK (x86_64) and TorchAO (ARM64) backend testing - Use --local-dir for hf download to avoid read-only /mnt/hf_cache issues - convert_weights now rewrites the no-op normalizer in Spark-X2.5 tokenizer.json (empty Sequence, rejected by older revisions of the C++ HF tokenizer) to null, which is semantically identical, so llama_main can load it. The root cause is also fixed upstream in meta-pytorch/tokenizers#225; the submodule pin will be bumped once that lands. The Spark-X2.5 model infrastructure already exists in the codebase. This commit completes the integration by adding automated CI testing. Parts of this commit were authored with AI assistance using Claude Code. Signed-off-by: dongjiang <dongjiang1989@126.com>
dongjiang1989
added a commit
to XHToken/executorch
that referenced
this pull request
Oct 28, 2026
This commit adds CI test support for Spark-X2.5-1.7B and Spark-X2.5-4B models to the ExecuTorch test infrastructure. Changes: - Added spark_x2_5_1_7b and spark_x2_5_4b to test_torchao_huggingface_checkpoints.sh - Added both models to CI test matrix in trunk.yml - Configured XNNPACK (x86_64) and TorchAO (ARM64) backend testing - Use --local-dir for hf download to avoid read-only /mnt/hf_cache issues - convert_weights now rewrites the no-op normalizer in Spark-X2.5 tokenizer.json (empty Sequence, rejected by older revisions of the C++ HF tokenizer) to null, which is semantically identical, so llama_main can load it. The root cause is also fixed upstream in meta-pytorch/tokenizers#225; the submodule pin will be bumped once that lands. The Spark-X2.5 model infrastructure already exists in the codebase. This commit completes the integration by adding automated CI testing. Parts of this commit were authored with AI assistance using Claude Code. Signed-off-by: dongjiang <dongjiang1989@126.com>
dongjiang1989
added a commit
to XHToken/executorch
that referenced
this pull request
Nov 2, 2026
This commit adds CI test support for Spark-X2.5-1.7B and Spark-X2.5-4B models to the ExecuTorch test infrastructure. Changes: - Added spark_x2_5_1_7b and spark_x2_5_4b to test_torchao_huggingface_checkpoints.sh - Added both models to CI test matrix in trunk.yml - Configured XNNPACK (x86_64) and TorchAO (ARM64) backend testing - Use --local-dir for hf download to avoid read-only /mnt/hf_cache issues - convert_weights now rewrites the no-op normalizer in Spark-X2.5 tokenizer.json (empty Sequence, rejected by older revisions of the C++ HF tokenizer) to null, which is semantically identical, so llama_main can load it. The root cause is also fixed upstream in meta-pytorch/tokenizers#225; the submodule pin will be bumped once that lands. The Spark-X2.5 model infrastructure already exists in the codebase. This commit completes the integration by adding automated CI testing. Parts of this commit were authored with AI assistance using Claude Code. Signed-off-by: dongjiang <dongjiang1989@126.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.
Problem
tokenizer.jsonfiles that are valid per the HuggingFace tokenizers spec can fail to load or encode incorrectly. Found while enabling CI for XHToken/Spark-X2.5 models in executorch (pytorch/executorch#23525).Bug 1: empty
Sequencenormalizer rejectedSpark-X2.5 ships
"normalizer": {"type": "Sequence", "normalizers": []}. An empty sequence is valid in the Rust implementation (it normalizes nothing), butNormalizerConfig::create()threwMissing normalizers for Normalizer of type Sequence, soHFTokenizer::load()failed withLoadFailure.Fix: allow an empty
normalizerslist;SequenceNormalizerwith no children is already the identity.Bug 2: Regex
Splitdropped non-matching textRegexPreTokenizertreated every Regex-patternSplitas "return the matches themselves". That is only correct forinvert=true, or for regexes that tile the input (GPT-2 / llama3 style), which is why it went unnoticed.Per the HF spec,
Splitwithinvert=falseuses matches as delimiters: text between matches must be kept, and thebehaviorfield (Removed/Isolated/MergedWithPrevious) applies to the delimiters.Spark-X2.5 isolates digits with
{"pattern": {"Regex": "\\p{N}{1,3}"}, "behavior": "Isolated", "invert": false}. For a prompt with no digits there are no matches, so the old code returned zero pieces andencode()produced zero tokens for ordinary text.Fix: a Regex pattern with an explicit
behaviorandinvert=falsenow uses delimiter semantics (the same code path String patterns already used).invert=trueand behavior-less configs keep the previous behavior, so existing configs (GPT-2, llama3, tekken, tiktoken) are unaffected — full ctest suite passes (15/15, includingtest_tekken,test_hf_tokenizer,test_pre_tokenizer).Tests
NormalizerTest.EmptySequenceNormalizerFromConfig— empty Sequence is a no-opPreTokenizerConfigTest.SplitWithRegexIsolatedKeepsNonMatchingText— non-tiling regex keeps text between matches; no-match input passes through wholePreTokenizerConfigTest.SplitWithRegexInvertTrueReturnsMatches—invert=trueunchangedEnd-to-end verification
Built against the real
XHToken/Spark-X2.5-1.7B/tokenizer.json(10MB BPE,Sequencepre-tokenizer with digit/CJK isolation, lookahead regex via PCRE2 fallback):