#![cfg(feature = "vocab-mistral")]
use splintr::{from_pretrained, AnyTokenizer, Tokenize};
use std::sync::LazyLock;
static TOKENIZER: LazyLock<AnyTokenizer> =
LazyLock::new(|| from_pretrained("mistral").expect("mistral loads"));
#[test]
fn mistral_v1_matches_sentencepiece_exactly() {
let cases: &[(&str, &[u32])] = &[
("the sourdough", &[272, 18193, 28715, 900]),
("sourdough", &[18193, 28715, 900]),
("hello world", &[6312, 28709, 1526]),
("Hello world", &[22557, 1526]),
(" Hello world", &[28705, 22557, 1526]),
("tokenizer", &[6029, 4024]),
("perplexity", &[660, 8899, 472]),
("Hello, world!", &[22557, 28725, 1526, 28808]),
("你好世界", &[28705, 29383, 29530, 30050, 29822]),
];
for (text, expected) in cases {
assert_eq!(
TOKENIZER.encode_raw(text),
*expected,
"sentencepiece reference mismatch for {text:?}"
);
}
}
#[test]
fn mistral_v1_keeps_a_leading_space_separate_from_the_next_word() {
let ids = TOKENIZER.encode_raw(" Hello world");
assert_eq!(ids.first().copied(), Some(28705), "leading ▁ in {ids:?}");
assert_eq!(ids, vec![28705, 22557, 1526]);
}
#[test]
fn mistral_v1_round_trips_every_reference_case() {
for text in [
"the sourdough",
"hello world",
" Hello world",
"Hello, world!",
"你好世界",
"perplexity",
] {
let ids = TOKENIZER.encode_raw(text);
let decoded = TOKENIZER.decode(&ids).expect("decodes");
assert_eq!(decoded, text, "round trip failed for {text:?}");
}
}
#[test]
fn mistral_v1_vocab_size_covers_the_agent_tokens() {
assert_eq!(TOKENIZER.vocab_size(), 32054);
}