mattrguerra/cortexmainPrivate on GitHub, published here in full

estimate.rs

Language Rust1.6 KB46 lines

crates/cortex-core/src/estimate.rs

  1. //! Token estimates, for when the server reports none: most local servers, a
  2. //! cancelled stream, an error part way. Also the composer's pre-send figure.
  3. //! Anything built on these is marked "est." in the interface.
  4. /// Roughly 4 characters per token for Latin script, 1 per CJK character.
  5. pub fn estimate_tokens(text: &str) -> i64 {
  6. let mut cjk = 0i64;
  7. let mut other = 0i64;
  8. for ch in text.chars() {
  9. let c = ch as u32;
  10. let wide = (0x3040..=0x30ff).contains(&c) // kana
  11. || (0x3400..=0x9fff).contains(&c) // CJK unified
  12. || (0xac00..=0xd7af).contains(&c) // hangul
  13. || (0xf900..=0xfaff).contains(&c);
  14. if wide {
  15. cjk += 1;
  16. } else {
  17. other += 1;
  18. }
  19. }
  20. cjk + (other + 3) / 4
  21. }
  22. /// Per-message overhead of the chat template.
  23. pub const MESSAGE_OVERHEAD: i64 = 4;
  24. /// A single image at the size Cortex sends it; real counts vary by model.
  25. pub const IMAGE_TOKENS: i64 = 765;
  26. /// A prompt of `(text, image_count)` messages.
  27. pub fn estimate_prompt<'a>(messages: impl IntoIterator<Item = (&'a str, usize)>) -> i64 {
  28. messages.into_iter().map(|(t, images)| estimate_tokens(t) + MESSAGE_OVERHEAD + images as i64 * IMAGE_TOKENS).sum()
  29. }
  30. #[cfg(test)]
  31. mod tests {
  32. use super::*;
  33. #[test]
  34. fn latin_and_cjk() {
  35. assert_eq!(estimate_tokens(""), 0);
  36. assert_eq!(estimate_tokens("abcd"), 1);
  37. assert_eq!(estimate_tokens("abcde"), 2);
  38. assert_eq!(estimate_tokens("\u{4f60}\u{597d}"), 2);
  39. assert_eq!(estimate_prompt([("abcd", 0), ("", 1)]), 1 + 4 + 4 + 765);
  40. }
  41. }