lc_core/token_counter/
tiktoken.rs1use tiktoken_rs::CoreBPE;
4
5use lc_schema::Message;
6
7use super::counter::TokenCounter;
8use super::TokenCounterError;
9
10pub struct TiktokenCounter {
12 encoder: CoreBPE,
13}
14
15impl TiktokenCounter {
16 pub fn new() -> Result<Self, TokenCounterError> {
18 let encoder = tiktoken_rs::cl100k_base()
19 .map_err(|e| TokenCounterError::EncoderLoad(e.to_string()))?;
20 Ok(Self { encoder })
21 }
22}
23
24impl TokenCounter for TiktokenCounter {
28 fn count_tokens(&self, text: &str) -> u32 {
29 self.encoder.encode_with_special_tokens(text).len() as u32
30 }
31
32 fn count_messages(&self, messages: &[Message]) -> u32 {
33 let mut total = 0u32;
34 for msg in messages {
35 total += 4; total += self.count_tokens(&msg.content);
37 if let Some(name) = &msg.name {
38 total += self.count_tokens(name);
39 }
40 for _ in &msg.images {
42 total += 1000;
43 }
44 }
45 total += 2; total
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn test_count_tokens_nonempty() {
56 let counter = TiktokenCounter::new().unwrap();
57 let n = counter.count_tokens("Hello, world!");
58 assert!(n > 0);
59 }
60
61 #[test]
62 fn test_count_tokens_empty() {
63 let counter = TiktokenCounter::new().unwrap();
64 assert_eq!(counter.count_tokens(""), 0);
65 }
66
67 #[test]
68 fn test_count_messages_includes_overhead() {
69 let counter = TiktokenCounter::new().unwrap();
70 let msgs = vec![Message::system("You are helpful."), Message::human("Hi")];
71 let n = counter.count_messages(&msgs);
72 assert!(n >= 10);
74 }
75
76 #[test]
77 fn test_count_messages_with_image() {
78 let counter = TiktokenCounter::new().unwrap();
79 let msg = Message::human_with_image("看图", "https://example.com/x.png");
80 let n = counter.count_messages(&[msg]);
81 assert!(n >= 1000); }
83
84 #[test]
85 fn test_longer_text_more_tokens() {
86 let counter = TiktokenCounter::new().unwrap();
87 let short = counter.count_tokens("hi");
88 let long = counter.count_tokens("This is a much longer sentence with many words.");
89 assert!(long > short);
90 }
91}