#![cfg(feature = "vocab-kimi")]
use splintr::pretrained::{from_pretrained, kimi_k2_special_tokens, kimi_k3_special_tokens};
use splintr::{AnyTokenizer, SpecialDecode, Tokenize};
use std::sync::LazyLock;
static K2: LazyLock<AnyTokenizer> =
LazyLock::new(|| from_pretrained("kimi_k2").expect("kimi_k2 is bundled"));
static K3: LazyLock<AnyTokenizer> =
LazyLock::new(|| from_pretrained("kimi_k3").expect("kimi_k3 is bundled"));
#[test]
fn kimi_encodes_the_reference_ids() {
for (text, expected) in [
("Hello world", vec![19180u32, 2695]),
("Hello, world!", vec![19180, 11, 2695, 0]),
("你好世界", vec![33845, 2243]),
("1234567890", vec![6694, 12972, 16242, 15]),
("中文English混合", vec![16717, 44372, 13935]),
] {
assert_eq!(K2.encode_raw(text), expected, "ids for {text:?}");
}
}
#[test]
fn kimi_splits_han_runs_into_their_own_pre_tokens() {
let split = |text: &str| K2.pre_tokenize(text).expect("Kimi has a pre-tokenizer");
assert_eq!(split("中文English混合"), ["中文", "English", "混合"]);
assert_eq!(split("汉字abc"), ["汉字", "abc"]);
assert_eq!(split("北京市 Pascal"), ["北京市", " Pascal"]);
}
#[test]
fn kimi_k2_and_k3_agree_on_every_ordinary_id() {
for text in [
"Hello world",
"The quick brown fox jumps over the lazy dog.",
"中文和English混合内容。",
"fn main() { println!(\"hi\"); }",
" indented\n\tand tabbed\r\n",
"🌍🌎🌏 emoji run",
"日本語のテキストです",
] {
assert_eq!(
K2.encode_raw(text),
K3.encode_raw(text),
"ids diverge for {text:?}"
);
}
}
#[test]
fn kimi_k2_and_k3_name_the_same_ids_differently() {
let k2 = kimi_k2_special_tokens();
let k3 = kimi_k3_special_tokens();
assert_eq!(k2.get("<|im_end|>"), Some(&163586));
assert_eq!(k3.get("<|end_of_msg|>"), Some(&163586));
assert_eq!(k2.get("<|im_user|>"), Some(&163587));
assert_eq!(k3.get("<|open|>"), Some(&163587));
assert_eq!(
K2.decode_with(&[163586], SpecialDecode::Render).unwrap(),
"<|im_end|>"
);
assert_eq!(
K3.decode_with(&[163586], SpecialDecode::Render).unwrap(),
"<|end_of_msg|>"
);
assert_eq!(
K3.decode_with(&[163594], SpecialDecode::Render).unwrap(),
"<|reserved_token_163594|>"
);
assert_eq!(
K2.decode_with(&[163594], SpecialDecode::Render).unwrap(),
"<|im_system|>"
);
for (name, id) in [("[BOS]", 163584u32), ("[EOS]", 163585), ("[PAD]", 163839)] {
assert_eq!(k2.get(name), Some(&id));
assert_eq!(k3.get(name), Some(&id));
}
}
#[test]
fn kimi_reserves_the_whole_256_slot_block() {
let special = kimi_k2_special_tokens();
let reserved = (163584..163840).filter(|id| special.values().any(|v| v == id));
assert_eq!(reserved.count(), 256, "every reserved id must have a name");
assert_eq!(
K2.decode_with(&[163700], SpecialDecode::Render).unwrap(),
"<|reserved_token_163700|>"
);
}
#[test]
fn kimi_round_trips() {
for text in [
"Hello world",
" leading and trailing ",
"中文和English混合内容。",
"日本語のテキストです",
"fn main() { println!(\"hi\"); }",
"",
] {
let ids = K2.encode_raw(text);
assert_eq!(K2.decode(&ids).expect("decodes"), text);
}
}
#[test]
fn kimi_recognizes_markers_in_text() {
let ids = K2.encode("<|im_user|>hello<|im_end|>");
assert_eq!(ids.first(), Some(&163587));
assert_eq!(ids.last(), Some(&163586));
}
#[test]
fn kimi_aliases_resolve_as_documented() {
let k2_ids = K2.encode_raw("Hello world");
for name in [
"kimi",
"kimi_k2",
"kimi-k2",
"kimi_k2.5",
"kimi-k2.5",
"kimi_linear",
] {
let alias = from_pretrained(name).expect("alias is bundled");
assert_eq!(alias.encode_raw("Hello world"), k2_ids, "alias {name}");
assert_eq!(
alias.decode_with(&[163586], SpecialDecode::Render).unwrap(),
"<|im_end|>",
"alias {name} must carry K2's markers"
);
}
for name in ["kimi_k3", "kimi-k3"] {
let alias = from_pretrained(name).expect("alias is bundled");
assert_eq!(
alias.decode_with(&[163586], SpecialDecode::Render).unwrap(),
"<|end_of_msg|>",
"alias {name} must carry K3's markers"
);
}
}
#[test]
fn kimi_reports_its_base_vocabulary_size() {
assert_eq!(
splintr::pretrained::base_vocab_size_by_name("kimi_k2").unwrap(),
163840
);
assert_eq!(
splintr::pretrained::base_vocab_size_by_name("kimi_k3").unwrap(),
163840
);
assert!(K2.vocab_size() > 163840, "agent tokens sit above it");
}