Coverage for wrapper/vibevoice/modular_vibevoice_text_tokenizer.py: 55%
65 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-09 04:47 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-09 04:47 +0000
1# mypy: ignore-errors
2# Copy from https://github.com/microsoft/VibeVoice/blob/main/vibevoice/modular/modular_vibevoice_text_tokenizer.py
4"""Tokenization classes for vibevoice."""
6from typing import Any
7from typing import Dict
8from typing import Optional
9from typing import cast
11from transformers.utils import logging
12from transformers.models.qwen2.tokenization_qwen2 import Qwen2Tokenizer
13# TODO this is gone now
14# from transformers.models.qwen2.tokenization_qwen2_fast import Qwen2TokenizerFast
16logger = logging.get_logger(__name__)
19class VibeVoiceTextTokenizer(Qwen2Tokenizer):
20 """
21 Construct a VibeVoice tokenizer. Based on the Qwen2 tokenizer with additional special tokens for speech.
22 Args:
23 vocab_file (`str`):
24 Path to the vocabulary file.
25 merges_file (`str`):
26 Path to the merges file.
27 errors (`str`, *optional*, defaults to `"replace"`):
28 Paradigm to follow when decoding bytes to UTF-8.
29 unk_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
30 The unknown token.
31 bos_token (`str`, *optional*):
32 The beginning of sequence token. Not used for vibevoice.
33 eos_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
34 The end of sequence token.
35 pad_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
36 The token used for padding.
37 add_special_tokens (`bool`, *optional*, defaults to `True`):
38 Whether or not to add special tokens when encoding.
39 """
41 model_input_names = ["input_ids", "attention_mask"]
43 def __init__(
44 self,
45 vocab_file: str,
46 merges_file: str,
47 errors: str = "replace",
48 unk_token: Optional[str] = "<|endoftext|>",
49 bos_token: Optional[str] = None,
50 eos_token: Optional[str] = "<|endoftext|>",
51 pad_token: Optional[str] = "<|endoftext|>",
52 add_prefix_space: bool = False,
53 add_special_tokens: bool = True,
54 **kwargs: Any,
55 ) -> None:
56 super().__init__(
57 vocab_file=vocab_file,
58 merges_file=merges_file,
59 errors=errors,
60 unk_token=unk_token or "<|endoftext|>",
61 bos_token=bos_token,
62 eos_token=eos_token or "<|endoftext|>",
63 pad_token=pad_token or "<|endoftext|>",
64 add_prefix_space=add_prefix_space,
65 add_special_tokens=add_special_tokens,
66 **kwargs,
67 )
69 # Add VibeVoice-specific special tokens
70 self._add_vibevoice_special_tokens()
72 def _add_vibevoice_special_tokens(self) -> int:
73 """Add VibeVoice-specific special tokens."""
74 special_tokens = {
75 "additional_special_tokens": [
76 "<|vision_start|>", # Speech start (reusing vision tokens)
77 "<|vision_end|>", # Speech end
78 "<|vision_pad|>", # Speech diffusion pad
79 ]
80 }
81 num_added = self.add_special_tokens(cast(Dict[str, Any], special_tokens))
83 # Cache special token IDs
84 self._speech_start_id = cast(int, self.convert_tokens_to_ids("<|vision_start|>"))
85 self._speech_end_id = cast(int, self.convert_tokens_to_ids("<|vision_end|>"))
86 self._speech_diffusion_id = cast(int, self.convert_tokens_to_ids("<|vision_pad|>"))
88 self._eos_id = cast(int, self.convert_tokens_to_ids('<|endoftext|>'))
90 return num_added
92 @property
93 def eos_id(self) -> int:
94 """Id of the end of sequence token."""
95 return self._eos_id
97 @property
98 def speech_start_id(self) -> int:
99 """Id of the speech start token."""
100 return self._speech_start_id
102 @property
103 def speech_end_id(self) -> int:
104 """Id of the speech end token."""
105 return self._speech_end_id
107 @property
108 def speech_diffusion_id(self) -> int:
109 """Id of the speech diffusion token."""
110 return self._speech_diffusion_id
112 @property
113 def pad_id(self) -> int:
114 """Id used for padding (returns -100 for loss masking)."""
115 return -100
118# class VibeVoiceTextTokenizerFast(Qwen2TokenizerFast):
119class VibeVoiceTextTokenizerFast(Qwen2Tokenizer):
120 """
121 Construct a "fast" VibeVoice tokenizer (backed by HuggingFace's *tokenizers* library).
122 Based on the Qwen2 tokenizer with additional special tokens for speech.
123 Args:
124 vocab_file (`str`, *optional*):
125 Path to the vocabulary file.
126 merges_file (`str`, *optional*):
127 Path to the merges file.
128 tokenizer_file (`str`, *optional*):
129 Path to [tokenizers](https://github.com/huggingface/tokenizers) file.
130 unk_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
131 The unknown token.
132 bos_token (`str`, *optional*):
133 The beginning of sequence token. Not used for vibevoice.
134 eos_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
135 The end of sequence token.
136 pad_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
137 The token used for padding.
138 """
140 model_input_names = ["input_ids", "attention_mask"]
142 def __init__(
143 self,
144 vocab_file: Optional[str] = None,
145 merges_file: Optional[str] = None,
146 tokenizer_file: Optional[str] = None,
147 unk_token: Optional[str] = "<|endoftext|>",
148 bos_token: Optional[str] = None,
149 eos_token: Optional[str] = "<|endoftext|>",
150 pad_token: Optional[str] = "<|endoftext|>",
151 add_prefix_space: bool = False,
152 **kwargs: Any,
153 ) -> None:
154 super().__init__(
155 vocab_file=vocab_file,
156 merges_file=merges_file,
157 tokenizer_file=tokenizer_file,
158 unk_token=unk_token or "<|endoftext|>",
159 bos_token=bos_token,
160 eos_token=eos_token or "<|endoftext|>",
161 pad_token=pad_token or "<|endoftext|>",
162 add_prefix_space=add_prefix_space,
163 **kwargs,
164 )
166 # Add VibeVoice-specific special tokens
167 self._add_vibevoice_special_tokens()
169 def _add_vibevoice_special_tokens(self) -> int:
170 """Add VibeVoice-specific special tokens."""
171 special_tokens = {
172 "additional_special_tokens": [
173 "<|vision_start|>", # Speech start (reusing vision tokens)
174 "<|vision_end|>", # Speech end
175 "<|vision_pad|>", # Speech diffusion pad
176 ]
177 }
178 num_added = self.add_special_tokens(cast(Dict[str, Any], special_tokens))
180 # Cache special token IDs
181 self._speech_start_id = cast(int, self.convert_tokens_to_ids("<|vision_start|>"))
182 self._speech_end_id = cast(int, self.convert_tokens_to_ids("<|vision_end|>"))
183 self._speech_diffusion_id = cast(int, self.convert_tokens_to_ids("<|vision_pad|>"))
185 # self._eos_id = self.convert_tokens_to_ids('<|endoftext|>')
186 self._eos_id = cast(int, self.eos_token_id) # qwen2 / qwen3
187 self._pad_id = cast(int, self.convert_tokens_to_ids('<|image_pad|>'))
189 return num_added
191 @property
192 def eos_id(self) -> int:
193 """Id of the end of sequence token."""
194 return self._eos_id
196 @property
197 def speech_start_id(self) -> int:
198 """Id of the speech start token."""
199 return self._speech_start_id
201 @property
202 def speech_end_id(self) -> int:
203 """Id of the speech end token."""
204 return self._speech_end_id
206 @property
207 def speech_diffusion_id(self) -> int:
208 """Id of the speech diffusion token."""
209 return self._speech_diffusion_id
211 @property
212 def pad_id(self) -> int:
213 """Id used for padding (returns -100 for loss masking)."""
214 return self._pad_id
217__all__ = [
218 "VibeVoiceTextTokenizer",
219 "VibeVoiceTextTokenizerFast",
220]