Skip to main content

logicaffeine_compile/model/tokenizer/
pre.rs

1//! The pre-tokenizers of byte-pair vocabularies: which `tokenizer.ggml.pre` names select which splitter, the regular
2//! expressions each one splits a fragment by (in order, each refining the spans of the last), and the vocabulary
3//! settings a name implies. The table is llama.cpp's (`llama-vocab.cpp`, `llm_tokenizer_bpe` and
4//! `llama_vocab::impl::load`); `model_tokenizer_lock` reads both tables out of the pinned source and holds this one
5//! equal to them.
6
7/// A byte-pair pre-tokenizer, named as llama.cpp's `LLAMA_VOCAB_PRE_TYPE_*`.
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
9pub enum PreType {
10    Default,
11    Llama3,
12    DeepseekLlm,
13    DeepseekCoder,
14    Falcon,
15    Mpt,
16    Starcoder,
17    Gpt2,
18    Refact,
19    CommandR,
20    Stablelm2,
21    Qwen2,
22    Qwen35,
23    Olmo,
24    Dbrx,
25    Smaug,
26    Poro,
27    Chatglm4,
28    Viking,
29    Jais,
30    Jais2,
31    Tekken,
32    Smollm,
33    Codeshell,
34    Bloom,
35    Gpt3Finnish,
36    Exaone,
37    ExaoneMoe,
38    Chameleon,
39    Minerva,
40    Deepseek3Llm,
41    Gpt4o,
42    GraniteEmbMulti,
43    TinyAya,
44    Superbpe,
45    Trillion,
46    GraniteDocling,
47    Bailingmoe,
48    SeedCoder,
49    Hunyuan,
50    HunyuanDense,
51    HyV4,
52    JoyaiLlm,
53    KimiK2,
54    Ufakzeka,
55    Grok2,
56    Afmoe,
57    Laguna,
58    MinimaxM2,
59    SolarOpen,
60    Mellum2,
61    K2Horizon,
62    Spark2_5,
63    Youtu,
64    Gemma4,
65    SarvamMoe,
66    Mmbert,
67    Minicpm5,
68    Whitespace,
69}
70
71/// The vocabulary settings a pre-tokenizer name implies, over the byte-pair defaults (`clean_spaces` on, the rest
72/// off). `None` leaves the default.
73#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
74pub struct PreSettings {
75    pub clean_spaces: Option<bool>,
76    pub ignore_merges: Option<bool>,
77    pub add_bos: Option<bool>,
78    pub escape_whitespaces: Option<bool>,
79    /// The name clears the default beginning-of-sequence token (`chatglm-bpe`, `glm4`, `glm5`).
80    pub no_bos_token: bool,
81    /// The name clears the lowercase normalizer (`whitespace`).
82    pub no_lowercase: bool,
83}
84
85const LLAMA3: &str = "(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+";
86const QWEN2: &str = "(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+";
87const GPT2: &str = "'s|'t|'re|'ve|'m|'ll|'d| ?\\p{L}+| ?\\p{N}+| ?[^\\s\\p{L}\\p{N}]+|\\s+(?!\\S)";
88const PORO: &str = " ?[^(\\s|.,!?…。,、।۔،)]+";
89const NEWLINES: &str = "[^\\n]+|[\\n]+";
90
91impl PreType {
92    /// llama.cpp's name for the type, without the `LLAMA_VOCAB_PRE_TYPE_` prefix.
93    pub fn llama_name(self) -> &'static str {
94        match self {
95            PreType::Default => "DEFAULT",
96            PreType::Llama3 => "LLAMA3",
97            PreType::DeepseekLlm => "DEEPSEEK_LLM",
98            PreType::DeepseekCoder => "DEEPSEEK_CODER",
99            PreType::Falcon => "FALCON",
100            PreType::Mpt => "MPT",
101            PreType::Starcoder => "STARCODER",
102            PreType::Gpt2 => "GPT2",
103            PreType::Refact => "REFACT",
104            PreType::CommandR => "COMMAND_R",
105            PreType::Stablelm2 => "STABLELM2",
106            PreType::Qwen2 => "QWEN2",
107            PreType::Qwen35 => "QWEN35",
108            PreType::Olmo => "OLMO",
109            PreType::Dbrx => "DBRX",
110            PreType::Smaug => "SMAUG",
111            PreType::Poro => "PORO",
112            PreType::Chatglm4 => "CHATGLM4",
113            PreType::Viking => "VIKING",
114            PreType::Jais => "JAIS",
115            PreType::Jais2 => "JAIS2",
116            PreType::Tekken => "TEKKEN",
117            PreType::Smollm => "SMOLLM",
118            PreType::Codeshell => "CODESHELL",
119            PreType::Bloom => "BLOOM",
120            PreType::Gpt3Finnish => "GPT3_FINNISH",
121            PreType::Exaone => "EXAONE",
122            PreType::ExaoneMoe => "EXAONE_MOE",
123            PreType::Chameleon => "CHAMELEON",
124            PreType::Minerva => "MINERVA",
125            PreType::Deepseek3Llm => "DEEPSEEK3_LLM",
126            PreType::Gpt4o => "GPT4O",
127            PreType::GraniteEmbMulti => "GRANITE_EMB_MULTI",
128            PreType::TinyAya => "TINY_AYA",
129            PreType::Superbpe => "SUPERBPE",
130            PreType::Trillion => "TRILLION",
131            PreType::GraniteDocling => "GRANITE_DOCLING",
132            PreType::Bailingmoe => "BAILINGMOE",
133            PreType::SeedCoder => "SEED_CODER",
134            PreType::Hunyuan => "HUNYUAN",
135            PreType::HunyuanDense => "HUNYUAN_DENSE",
136            PreType::HyV4 => "HY_V4",
137            PreType::JoyaiLlm => "JOYAI_LLM",
138            PreType::KimiK2 => "KIMI_K2",
139            PreType::Ufakzeka => "UFAKZEKA",
140            PreType::Grok2 => "GROK_2",
141            PreType::Afmoe => "AFMOE",
142            PreType::Laguna => "LAGUNA",
143            PreType::MinimaxM2 => "MINIMAX_M2",
144            PreType::SolarOpen => "SOLAR_OPEN",
145            PreType::Mellum2 => "MELLUM2",
146            PreType::K2Horizon => "K2_HORIZON",
147            PreType::Spark2_5 => "SPARK2_5",
148            PreType::Youtu => "YOUTU",
149            PreType::Gemma4 => "GEMMA4",
150            PreType::SarvamMoe => "SARVAM_MOE",
151            PreType::Mmbert => "MMBERT",
152            PreType::Minicpm5 => "MINICPM5",
153            PreType::Whitespace => "WHITESPACE",
154        }
155    }
156
157    /// Every type, in declaration order.
158    pub const ALL: [PreType; 59] = [
159        PreType::Default,
160        PreType::Llama3,
161        PreType::DeepseekLlm,
162        PreType::DeepseekCoder,
163        PreType::Falcon,
164        PreType::Mpt,
165        PreType::Starcoder,
166        PreType::Gpt2,
167        PreType::Refact,
168        PreType::CommandR,
169        PreType::Stablelm2,
170        PreType::Qwen2,
171        PreType::Qwen35,
172        PreType::Olmo,
173        PreType::Dbrx,
174        PreType::Smaug,
175        PreType::Poro,
176        PreType::Chatglm4,
177        PreType::Viking,
178        PreType::Jais,
179        PreType::Jais2,
180        PreType::Tekken,
181        PreType::Smollm,
182        PreType::Codeshell,
183        PreType::Bloom,
184        PreType::Gpt3Finnish,
185        PreType::Exaone,
186        PreType::ExaoneMoe,
187        PreType::Chameleon,
188        PreType::Minerva,
189        PreType::Deepseek3Llm,
190        PreType::Gpt4o,
191        PreType::GraniteEmbMulti,
192        PreType::TinyAya,
193        PreType::Superbpe,
194        PreType::Trillion,
195        PreType::GraniteDocling,
196        PreType::Bailingmoe,
197        PreType::SeedCoder,
198        PreType::Hunyuan,
199        PreType::HunyuanDense,
200        PreType::HyV4,
201        PreType::JoyaiLlm,
202        PreType::KimiK2,
203        PreType::Ufakzeka,
204        PreType::Grok2,
205        PreType::Afmoe,
206        PreType::Laguna,
207        PreType::MinimaxM2,
208        PreType::SolarOpen,
209        PreType::Mellum2,
210        PreType::K2Horizon,
211        PreType::Spark2_5,
212        PreType::Youtu,
213        PreType::Gemma4,
214        PreType::SarvamMoe,
215        PreType::Mmbert,
216        PreType::Minicpm5,
217        PreType::Whitespace,
218    ];
219
220    /// The patterns that split a fragment, applied in order.
221    pub fn regexes(self) -> &'static [&'static str] {
222        match self {
223            PreType::Llama3 | PreType::Dbrx | PreType::Smaug | PreType::Chatglm4 => &[LLAMA3],
224            PreType::Jais2 => &["(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s{512}(?!\\S)|\\s{256}(?!\\S)|\\s{128}(?!\\S)|\\s{64}(?!\\S)|\\s{32}(?!\\S)|\\s{16}(?!\\S)|\\s{8}(?!\\S)|\\s{4}(?!\\S)|\\s{1,2}(?!\\S)|\\s{1}"],
225            PreType::DeepseekLlm => &[
226                "[\r\n]",
227                "\\s?[A-Za-zµÀ-ÖØ-öø-ƺƼ-ƿDŽ-ʓʕ-ʯͰ-ͳͶͷͻ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-ՖႠ-ჅᎠ-Ᏽᏸ-ᏽᲐ-ᲺᲽ-Ჿᴀ-ᴫᵫ-ᵷᵹ-ᶚḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℴℹℼ-ℿⅅ-ⅉⅎↃↄⰀ-ⱻⱾ-ⳤⳫ-ⳮⳲⳳꙀ-ꙭꚀ-ꚛꜢ-ꝯꝱ-ꞇꞋ-ꞎꭰ-ꮿff-stﬓ-ﬗA-Za-z𐐀-𐑏𐒰-𐓓𐓘-𐓻𐲀-𐲲𐳀-𐳲𑢠-𑣟𞤀-𞥃]+",
228                "\\s?[!-/:-~!-/:-~‘-‟ -。]+",
229                "\\s+$",
230                "[一-龥ࠀ-一가-퟿]+",
231                "\\p{N}+",
232            ],
233            PreType::Deepseek3Llm | PreType::HunyuanDense | PreType::JoyaiLlm | PreType::HyV4 => &[
234                "\\p{N}{1,3}",
235                "[一-龥぀-ゟ゠-ヿ]+",
236                "[!\"#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_`{|}~][A-Za-z]+|[^\r\n\\p{L}\\p{P}\\p{S}]?[\\p{L}\\p{M}]+| ?[\\p{P}\\p{S}]+[\r\n]*|\\s*[\r\n]+|\\s+(?!\\S)|\\s+",
237            ],
238            PreType::Spark2_5 => &[
239                "\\p{N}{1,3}",
240                "[一-龥぀-ゟ゠-ヿ]+",
241                "[!\"#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_`{|}~][A-Za-z]+|[^\r\n\\p{L}\\p{P}\\p{S}]?[\\p{L}\\p{M}]+| ?[\\p{P}\\p{S}]+|[\r\n]|\\s+(?!\\S)|\\s+",
242                "\\p{N}",
243            ],
244            PreType::Youtu => &[
245                "[가-힣ㄱ-ㆎ]+|[!…“”‘’—:;,、-〿︰-﹏]+|[ㄅ-ㄯ]+|[一-龥぀-ゟ゠-ヿ]+",
246                "[^\\r\\n\\p{L}\\p{N}]?[\\p{Lu}\\p{Lt}\\p{Lm}\\p{Lo}\\p{M}]*[\\p{Ll}\\p{Lm}\\p{Lo}\\p{M}]+(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])?|[^\\r\\n\\p{L}\\p{N}]?[\\p{Lu}\\p{Lt}\\p{Lm}\\p{Lo}\\p{M}]+[\\p{Ll}\\p{Lm}\\p{Lo}\\p{M}]*(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])?|\\p{N}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n/]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+",
247            ],
248            PreType::DeepseekCoder => &["[\r\n]", "\\s?\\p{L}+", "\\s?\\p{P}+", "[一-龥ࠀ-一가-퟿]+", "\\p{N}"],
249            PreType::Falcon => &[
250                "[\\p{P}\\$\\+<=>\\^~\\|`]+",
251                GPT2,
252                "[0-9][0-9][0-9]",
253            ],
254            PreType::Starcoder
255            | PreType::Refact
256            | PreType::CommandR
257            | PreType::Smollm
258            | PreType::Codeshell
259            | PreType::Exaone
260            | PreType::Minerva
261            | PreType::Mellum2 => &["\\p{N}", GPT2],
262            PreType::Gpt2 | PreType::Mpt | PreType::Olmo | PreType::Jais | PreType::Trillion | PreType::GraniteDocling => {
263                &[GPT2]
264            }
265            PreType::Stablelm2 | PreType::Qwen2 | PreType::Hunyuan | PreType::SolarOpen => &[QWEN2],
266            PreType::Qwen35 => &["(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])|[^\\r\\n\\p{L}\\p{N}]?[\\p{L}\\p{M}]+|\\p{N}| ?[^\\s\\p{L}\\p{M}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"],
267            PreType::Poro | PreType::Bloom | PreType::Gpt3Finnish => &[PORO],
268            PreType::Viking => &[PORO, "\\p{N}"],
269            PreType::Tekken => &["[^\\r\\n\\p{L}\\p{N}]?((?=[\\p{L}])([^a-z]))*((?=[\\p{L}])([^A-Z]))+|[^\\r\\n\\p{L}\\p{N}]?((?=[\\p{L}])([^a-z]))+((?=[\\p{L}])([^A-Z]))*|\\p{N}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n/]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"],
270            PreType::Chameleon => &[
271                "<sentinel:[0-9]+>",
272                "(IMGIMG)((A|B|C|D|E|F|G|H|I){1,4})Z",
273                "([\\t\\n]|    |  )",
274                "\\p{N}",
275                "[\\p{P}!-/:-@\\[-`{-~]",
276                GPT2,
277            ],
278            PreType::Gpt4o | PreType::MinimaxM2 => &["[^\\r\\n\\p{L}\\p{N}]?((?=[\\p{L}])([^a-z]))*((?=[\\p{L}])([^A-Z]))+(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])?|[^\\r\\n\\p{L}\\p{N}]?((?=[\\p{L}])([^a-z]))+((?=[\\p{L}])([^A-Z]))*(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])?|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n/]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"],
279            PreType::GraniteEmbMulti => &["[^\\r\\n\\p{L}\\p{N}]?((?=[\\p{L}\\p{M}])([^a-z]))*((?=[\\p{L}\\p{M}])([^A-Z]))+(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])?|[^\\r\\n\\p{L}\\p{N}]?((?=[\\p{L}\\p{M}])([^a-z]))+((?=[\\p{L}\\p{M}])([^A-Z]))*(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])?|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n/]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"],
280            PreType::TinyAya => &[
281                "\\d{1,3}(?=(?:\\d{3})*\\b)",
282                "[^\\r\\n\\p{L}\\p{N}]?[\\p{Lu}\\p{Lt}\\p{Lm}\\p{Lo}\\p{M}]*[\\p{Ll}\\p{Lm}\\p{Lo}\\p{M}]+(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])?|[^\\r\\n\\p{L}\\p{N}]?[\\p{Lu}\\p{Lt}\\p{Lm}\\p{Lo}\\p{M}]+[\\p{Ll}\\p{Lm}\\p{Lo}\\p{M}]*(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])?|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n/]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+",
283            ],
284            PreType::KimiK2 => &["\\p{Han}+"],
285            PreType::Superbpe => &["\\p{N}+", "(?=(\\d{3})+(?!\\d))"],
286            PreType::Bailingmoe => &["'(?:[sSdDmMtT]|[lL][lL]|[vV][eE]|[rR][eE])|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]|\\s+(?!\\S)|\\s+"],
287            PreType::SeedCoder => &["(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1}| ?[^\\s\\p{L}\\p{N}\\r\\n]+|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"],
288            PreType::Ufakzeka => &["[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"],
289            PreType::Grok2 => &[QWEN2],
290            PreType::Afmoe => &[
291                "\\p{AFMoE_digits}",
292                "[一-鿿㐀-䶿豈-﫿぀-ゟ゠-ヿ・-゚⼀-⿟เ-๿຀-໿ក-៿က-႟ꩠ-ꩿꧠ-꧿가-힯ᄀ-ᇿ]+",
293                "[!\"#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_`{|}~][A-Za-z]+|[^\\r\\n\\p{L}\\p{P}\\p{S}]?[\\p{L}\\p{M}]+| ?[\\p{P}\\p{S}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+",
294            ],
295            PreType::Laguna => &[NEWLINES, QWEN2],
296            PreType::ExaoneMoe => &["(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])|[^\\r\\n\\p{L}\\p{N}]?(?:\\p{L}\\p{M}*(?: \\p{L}\\p{M}*)*)+|\\p{N}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n/]?|\\s*[\\r\\n]|\\s+(?!\\S)|\\s+"],
297            PreType::Gemma4 | PreType::SarvamMoe | PreType::Mmbert => &[NEWLINES],
298            PreType::Minicpm5 => &[
299                "\\p{N}{1,3}",
300                "(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}+| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+",
301            ],
302            PreType::K2Horizon => &["(?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])|[^\\r\\n\\p{L}\\p{N}]?(?:\\p{L}|\\p{M}|\\u200C|\\u200D)+|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"],
303            PreType::Whitespace => &["\\S+"],
304            PreType::Default => &[
305                "[\\p{P}\\$\\+<=>\\^~\\|]+",
306                GPT2,
307                "\\p{N}+",
308                "[0-9][0-9][0-9]",
309            ],
310        }
311    }
312
313    /// Whether a split word is written in GPT-2's byte alphabet before merging (raw UTF-8 otherwise).
314    pub fn byte_encode(self) -> bool {
315        !matches!(self, PreType::Gemma4 | PreType::SarvamMoe | PreType::Mmbert | PreType::Whitespace)
316    }
317}
318
319/// The pre-tokenizer a `tokenizer.ggml.pre` name selects, with the settings it implies; `None` for a name llama.cpp
320/// does not know (it refuses the model). An absent name reads as `"default"`.
321pub fn pre_type(name: &str) -> Option<(PreType, PreSettings)> {
322    let s = PreSettings::default;
323    let no_clean = || PreSettings { clean_spaces: Some(false), ..s() };
324    Some(match name {
325        "default" => (PreType::Default, s()),
326        "minicpm5" => (PreType::Minicpm5, PreSettings { ignore_merges: Some(true), ..s() }),
327        "llama3" | "llama-v3" | "llama-bpe" | "falcon3" | "falcon-h1" | "pixtral" | "midm-2.0" | "lfm2"
328        | "jina-v5-nano" => (PreType::Llama3, PreSettings { ignore_merges: Some(true), add_bos: Some(true), ..s() }),
329        "deepseek-llm" => (PreType::DeepseekLlm, no_clean()),
330        "deepseek-coder" => (PreType::DeepseekCoder, no_clean()),
331        "deepseek-v3" => (PreType::Deepseek3Llm, no_clean()),
332        "spark2_5" => (PreType::Spark2_5, no_clean()),
333        "youtu" => (PreType::Youtu, PreSettings { ignore_merges: Some(true), ..no_clean() }),
334        "falcon" => (PreType::Falcon, s()),
335        "mpt" => (PreType::Mpt, s()),
336        "starcoder" => (PreType::Starcoder, s()),
337        "gpt-2" | "phi-2" | "jina-es" | "jina-de" | "gigachat" | "jina-v2-es" | "jina-v2-de" | "a.x-4.0" | "mellum"
338        | "modern-bert" => (PreType::Gpt2, s()),
339        "jais-2" => (PreType::Jais2, s()),
340        "gemma4" | "granite-embed-multi-311m" => {
341            (PreType::Gemma4, PreSettings { escape_whitespaces: Some(true), ..s() })
342        }
343        "mmbert" => (PreType::Mmbert, PreSettings { escape_whitespaces: Some(true), ..s() }),
344        "sarvam-moe" => (PreType::SarvamMoe, PreSettings { escape_whitespaces: Some(true), ..no_clean() }),
345        "jina-v1-en" | "jina-v2-code" | "roberta-bpe" => (PreType::Gpt2, s()),
346        "whitespace" => (PreType::Whitespace, PreSettings { no_lowercase: true, ..s() }),
347        "refact" => (PreType::Refact, s()),
348        "command-r" => (PreType::CommandR, no_clean()),
349        "qwen2" | "deepseek-r1-qwen" | "kormo" | "f2llmv2" => (PreType::Qwen2, no_clean()),
350        "qwen35" => (PreType::Qwen35, no_clean()),
351        "stablelm2" => (PreType::Stablelm2, s()),
352        "olmo" => (PreType::Olmo, s()),
353        "dbrx" => (PreType::Dbrx, s()),
354        "smaug-bpe" => (PreType::Smaug, s()),
355        "poro-chat" => (PreType::Poro, no_clean()),
356        "chatglm-bpe" => (PreType::Chatglm4, PreSettings { no_bos_token: true, ..s() }),
357        "glm4" | "glm5" => {
358            (PreType::Chatglm4, PreSettings { no_bos_token: true, ignore_merges: Some(true), ..s() })
359        }
360        "viking" => (PreType::Viking, no_clean()),
361        "jais" => (PreType::Jais, s()),
362        "tekken" => (
363            PreType::Tekken,
364            PreSettings { ignore_merges: Some(true), add_bos: Some(true), ..no_clean() },
365        ),
366        "smollm" => (PreType::Smollm, no_clean()),
367        "codeshell" => (PreType::Codeshell, s()),
368        "bloom" => (PreType::Bloom, s()),
369        "gpt3-finnish" => (PreType::Gpt3Finnish, s()),
370        "exaone" => (PreType::Exaone, s()),
371        "exaone4" => (PreType::Gpt2, s()),
372        "exaone-moe" => (PreType::ExaoneMoe, s()),
373        "chameleon" => (PreType::Chameleon, PreSettings { add_bos: Some(true), ..no_clean() }),
374        "minerva-7b" => (PreType::Minerva, s()),
375        "megrez" => (PreType::Qwen2, s()),
376        "gpt-4o" | "llama4" | "kanana2" | "talkie" => (PreType::Gpt4o, no_clean()),
377        "granite-embed-multi-97m" => {
378            (PreType::GraniteEmbMulti, PreSettings { ignore_merges: Some(true), ..no_clean() })
379        }
380        "tiny_aya" | "cohere2moe" => (PreType::TinyAya, no_clean()),
381        "superbpe" => (PreType::Superbpe, no_clean()),
382        "trillion" => (PreType::Trillion, no_clean()),
383        "granite-docling" => (PreType::GraniteDocling, no_clean()),
384        "bailingmoe" | "bailingmoe2" | "llada-moe" => (PreType::Bailingmoe, no_clean()),
385        "seed-coder" => (PreType::SeedCoder, no_clean()),
386        "hunyuan" => (PreType::Hunyuan, no_clean()),
387        "hunyuan-dense" => (PreType::HunyuanDense, no_clean()),
388        "hy_v4" => (PreType::HyV4, no_clean()),
389        "joyai-llm" => (PreType::JoyaiLlm, no_clean()),
390        "kimi-k2" => (PreType::KimiK2, no_clean()),
391        "ufakzeka" => (PreType::Ufakzeka, no_clean()),
392        "grok-2" => (PreType::Grok2, no_clean()),
393        "afmoe" => (PreType::Afmoe, no_clean()),
394        "laguna" => (PreType::Laguna, no_clean()),
395        "minimax-m2" => (PreType::MinimaxM2, no_clean()),
396        "solar-open" => (PreType::SolarOpen, no_clean()),
397        "mellum2" => (PreType::Mellum2, s()),
398        "k2-horizon" => (PreType::K2Horizon, no_clean()),
399        _ => return None,
400    })
401}