estimate.rs
Language Rust1.6 KB46 lines
//! Token estimates, for when the server reports none: most local servers, a//! cancelled stream, an error part way. Also the composer's pre-send figure.//! Anything built on these is marked "est." in the interface./// Roughly 4 characters per token for Latin script, 1 per CJK character.pub fn estimate_tokens(text: &str) -> i64 {let mut cjk = 0i64;let mut other = 0i64;for ch in text.chars() {let c = ch as u32;let wide = (0x3040..=0x30ff).contains(&c) // kana|| (0x3400..=0x9fff).contains(&c) // CJK unified|| (0xac00..=0xd7af).contains(&c) // hangul|| (0xf900..=0xfaff).contains(&c);if wide {cjk += 1;} else {other += 1;}}cjk + (other + 3) / 4}/// Per-message overhead of the chat template.pub const MESSAGE_OVERHEAD: i64 = 4;/// A single image at the size Cortex sends it; real counts vary by model.pub const IMAGE_TOKENS: i64 = 765;/// A prompt of `(text, image_count)` messages.pub fn estimate_prompt<'a>(messages: impl IntoIterator<Item = (&'a str, usize)>) -> i64 {messages.into_iter().map(|(t, images)| estimate_tokens(t) + MESSAGE_OVERHEAD + images as i64 * IMAGE_TOKENS).sum()}#[cfg(test)]mod tests {use super::*;#[test]fn latin_and_cjk() {assert_eq!(estimate_tokens(""), 0);assert_eq!(estimate_tokens("abcd"), 1);assert_eq!(estimate_tokens("abcde"), 2);assert_eq!(estimate_tokens("\u{4f60}\u{597d}"), 2);assert_eq!(estimate_prompt([("abcd", 0), ("", 1)]), 1 + 4 + 4 + 765);}}