Load the tokenizer and resolve EOS token ID(s). `default_eos_token` is the model-specific fallback (e.g. "<|eot_id|>" for LLaMA, "<|endoftext|>" for Qwen2).
(
ctx: &Context,
default_eos_token: &str,
)
| 17 | /// `default_eos_token` is the model-specific fallback (e.g. "<|eot_id|>" for LLaMA, |
| 18 | /// "<|endoftext|>" for Qwen2). |
| 19 | pub fn load_tokenizer( |
| 20 | ctx: &Context, |
| 21 | default_eos_token: &str, |
| 22 | ) -> Result<(Tokenizer, Option<EosTokenId>)> { |
| 23 | // For GGUF files, look for tokenizer.json in the same directory as the .gguf file |
| 24 | let tokenizer_filename = if ctx.data_path.is_file() { |
| 25 | ctx.data_path |
| 26 | .parent() |
| 27 | .unwrap_or(&ctx.data_path) |
| 28 | .join("tokenizer.json") |
| 29 | } else { |
| 30 | ctx.data_path.join("tokenizer.json") |
| 31 | }; |
| 32 | |
| 33 | log::info!("loading tokenizer from {}", tokenizer_filename.display()); |
| 34 | |
| 35 | let tokenizer = Tokenizer::from_file(tokenizer_filename).map_err(anyhow::Error::msg)?; |
| 36 | |
| 37 | let config = ctx.config.as_ref().expect("No config specified"); |
| 38 | |
| 39 | let eos_token_id = if config.eos_token_id.is_some() { |
| 40 | config.eos_token_id.clone() |
| 41 | } else { |
| 42 | // Fallback: try to resolve from tokenizer vocabulary |
| 43 | tokenizer |
| 44 | .token_to_id(default_eos_token) |
| 45 | .map(EosTokenId::Single) |
| 46 | }; |
| 47 | |
| 48 | Ok((tokenizer, eos_token_id)) |
| 49 | } |
| 50 | |
| 51 | /// Apply repeat penalty entirely on GPU to avoid costly GPU↔CPU round-trips. |
| 52 | /// |