openvinotoolkit/openvino_tokenizers/tokenizer-fix-python
Claude Code and agent skill by openvinotoolkit/openvino_tokenizers
- community
Checking that the SKILL.md file is still in the repository.
Fix Python conversion issues in OpenVINO Tokenizers. Use when: tokenizer-diagnostics reports root_cause_location=python, unsupported types need new handlers in hf_parser.py, pipeline step mapping or merging is incorrect, tokenizer_pipeline.py step classes need fixes.
Install
npx vskill@latest install openvinotoolkit/openvino_tokenizers/tokenizer-fix-pythonSKILL.md
OpenVINO Tokenizer Python Fixer
Fixes issues in the Python conversion layer that maps HuggingFace tokenizer pipelines to OpenVINO Tokenizers.
When to Use
tokenizer-diagnosticsreportedroot_cause_location: python- Common issue categories:
- Unsupported type: A HuggingFace step type is missing from the parser maps
- Incorrect mapping: A supported type produces wrong OV steps (wrong params, missing steps)
- Merge bug:
merge_regex_split_stepsincorrectly combines incompatibleRegexSplitStepinstances duringfinalize() - Missing pipeline step class: A new OV operation needs a Python step wrapper
Inputs
Required:
- model_id: HuggingFace model identifier
- diagnosis: Output from the
tokenizer-diagnosticsskill, particularly: unsupported_types— which HF types need handlersaffected_stages— which pipeline stages divergedescription— human-readable root cause summary
Helpful context (from tokenizer-diagnostics output):
- The HF→OV pipeline mapping (Step 2 output)
- Finalized pipeline showing step merges
- Pre-tokenization expected vs actual token splits
Prerequisites
Activate the Python virtual environment before running any commands.
- Locate the virtual environment — check for common directories at the repository root:
.venv/,venv/,env/. Uselist_dirto find it. If none is found, ask the user for its location. - Activate based on the current platform:
- Linux/macOS:
source <venv_path>/bin/activate - Windows (cmd):
<venv_path>\Scripts\activate.bat - Windows (PowerShell):
<venv_path>\Scripts\Activate.ps1
Architecture Overview
Conversion Pipeline
Key Files
| File | Purpose | |
|---|---|---|
python/openvino_tokenizers/hf_parser.py | Parser with type→handler maps for all pipeline sections | |
python/openvino_tokenizers/tokenizer_pipeline.py | Pipeline step dataclasses, TokenizerPipeline, finalize() | |
python/openvino_tokenizers/convert_tokenizer.py | Entry point: dispatches to fast/sentencepiece/tiktoken converters | |
src/ov_extension.cpp | C++ operation registration (lists all available ops) |
Parser Maps (hf_parser.py)
The parser uses four type→handler dictionaries. Each handler takes a step_dict (from tokenizer.json) and returns one or more *Step instances:
| Map | Pipeline Section | Approx Line | |
|---|---|---|---|
normalizers_map | tokenizer.json["normalizer"] | ~L194 | |
pre_tokenization_map | tokenizer.json["pre_tokenizer"] | ~L229 | |
post_tokenization_map | tokenizer.json["post_processor"] | ~L279 | |
decoding_map | tokenizer.json["decoder"] | ~L367 |
The tokenization model (BPE/WordPiece/Unigram/WordLevel) is handled by the tokenization_model() method (~L265), not via a map.
Step Class Hierarchy (tokenizer_pipeline.py)
Available C++ Operations (src/ov_extension.cpp)
RegexNormalization, RegexSplit, BPETokenizer, WordpieceTokenizer, BytesToChars, CharsToBytes, CombineSegments, VocabEncoder, VocabDecoder, TrieTokenizer, Truncate, FuzeRagged, ByteFallback, SpecialTokensSplit, CharsMapNormalization, CaseFold, NormalizeUnicode, UnigramTokenizer, UTF8Validate, SentencepieceTokenizer, SentencepieceDetokenizer, SentencepieceStreamDetokenizer, RaggedToDense, RaggedToSparse, RaggedToRagged, StringToHashBucket, StringTensorPack, StringTensorUnpack, RaggedTensorPack, EqualStr
Procedure
Step 1: Extract the tokenizer.json structure
Download and inspect the HF tokenizer's pipeline definition:
Alternatively, use openvino_tokenizers diagnose <model_id> output which already maps all sections.
Step 2: Identify the fix category
Based on the diagnosis, determine which category the fix falls into:
Category A: Missing type in parser map
Symptom: unsupported_types: [SomeType] in diagnosis output.
Fix pattern:
- Read the HF tokenizers source or
tokenizer.jsonspec to understand whatSomeTypedoes - Find or create the corresponding OV step class in
tokenizer_pipeline.py - Add the handler to the appropriate map in
hf_parser.py:
If a new step class is needed:
The get_ov_subgraph pattern:
- Extend
input_nodeswith constant parameters (strings viacreate_string_constant_node, scalars viamake_constant_node) - Call
_get_factory().create("<OpName>", input_nodes, {attributes_dict})to create the OV C++ operation - Return
.outputs()— the list of output nodes
Category B: Incorrect parameter parsing
Symptom: Conversion succeeds but outputs differ. Diagnosis shows no unsupported types but pre-tokenization or full pipeline tests fail.
Fix pattern:
- Read the HF
tokenizer.jsonfor the failing step and compare with the parser handler - Common issues:
- Reading wrong key from
step_dict(e.g."String"vs"Regex"in pattern dicts) - Missing boolean flags that affect behavior
- Default values that don't match HF defaults
Example — how handler reads a pattern dict:
Category C: Pipeline merge bug (merge_regex_split_steps)
Symptom: Diagnosis shows ⚠ Pre-tokenization merge: N steps → M steps and pre-tokenization test fails. The merged regex pattern in the finalized pipeline produces different splits than running the original patterns sequentially.
Where: TokenizerPipeline.merge_regex_split_steps() in tokenizer_pipeline.py (~L1498).
How it works: The method iterates over RegexSplitStep instances and tries to combine them via RegexSplitStep.__add__, which joins patterns with | (OR). It merges when invert, behaviour, and max_splits all match.
Common fix approaches:
- Prevent merge for incompatible patterns: Add a check in
RegexSplitStep.__add__that raisesValueErrorwhen patterns can't be safely merged (the merge loop catchesValueErrorand keeps steps separate):
- Skip merge entirely for specific step configurations: Add a
mergeableflag or check specific pattern signatures that are known to conflict.
- Fix the merge logic: If the
|-join is semantically wrong for certain pattern combinations, the patterns may need wrapping in non-capturing groups(?:pattern1)|(?:pattern2)or the merge should be skipped.
Category D: Step finalization issue
Symptom: Individual step mapping looks correct but the finalized pipeline differs unexpectedly.
Where: TokenizerPipeline.finalize() in tokenizer_pipeline.py (~L1547) and individual Step.finalize() methods.
Key finalization behaviors to be aware of:
BPETokenizationStep.finalize()(~L665): RemovesBytesToCharsStepandCharsToBytesStepfrom the pipeline whenis_byte_level=True, absorbing byte-level encoding into the BPE vocabmerge_regex_split_steps()(~L1498): Merges compatibleRegexSplitStepinstancesdel_duplicated_split_steps(): Removes duplicate whitespace splittersupdate_metaspace_step_with_special_tokens(): Patches metaspace regex when special tokens exist
Step 3: Implement the fix
- Read the relevant source files to understand the current implementation
- Apply the minimal fix — do not refactor surrounding code
- Ensure the fix handles edge cases present in the test strings:
- Whitespace variants:
\t,\n, multiple spaces - Empty strings
- Unicode: emoji, CJK, accented characters, RTL
- Mixed content: digits + letters + punctuation
Step 4: Verify
After applying the fix, rebuild and test:
Step 5: Check for regressions
The fix must not break other tokenizers. Key model sets to verify:
- WordPiece models:
bert-base-multilingual-cased,google/mobilebert-uncased - BPE models:
openai-community/gpt2,roberta-base,NousResearch/Meta-Llama-3-8B-Instruct - SentencePiece models:
NousResearch/Llama-2-13b-hf,microsoft/Phi-3-mini-128k-instruct - TikToken models:
Qwen/Qwen-14B-Chat
At minimum, run openvino_tokenizers check against 2-3 models of the same type as the fixed tokenizer.
Common Pitfalls
- Don't forget `parse()`:
TransformersTokenizerPipelineParser.__init__does NOT populate the pipeline — you must callparser.parse()first.
- Handler return types: Map handlers must return either a single
*Stepinstance or alist[*Step]. The parser wraps singles in lists internally.
- Regex dialect: OV uses PCRE2 regex (via the C++
RegexSplit/RegexNormalizationops). HF's Rust tokenizers uses thefancy-regexcrate. Key differences: Unicode property classes (\p{L},\p{N}) are supported in both, but lookahead/lookbehind support may differ.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryChecking.github/skills/tokenizer-fix-python/SKILL.md
Popularity
- Repository stars
- 53
- Repository forks
- 56
- 7-day trend score
- 20
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/openvinotoolkit/openvino_tokenizers/tokenizer-fix-python)