language_barrier_core/
compactor.rs1use crate::token::TokenCounter;
2
3pub trait ChatHistoryCompactor: Send + Sync + Clone {
5 fn compact(
10 &self,
11 history: &mut Vec<crate::message::Message>,
12 counter: &mut TokenCounter,
13 max_tokens: usize,
14 );
15}
16
17#[derive(Debug, Default, Clone)]
19pub struct DropOldestCompactor {}
20
21impl ChatHistoryCompactor for DropOldestCompactor {
22 fn compact(
23 &self,
24 history: &mut Vec<crate::message::Message>,
25 counter: &mut TokenCounter,
26 max_tokens: usize,
27 ) {
28 if history.is_empty() || counter.under_budget(max_tokens) {
30 return;
31 }
32
33 while !counter.under_budget(max_tokens) && history.len() > 1 {
35 let removed_msg = history.remove(0);
37
38 match &removed_msg {
40 crate::message::Message::User { content, .. } => {
41 match content {
42 crate::message::Content::Text(text) => {
43 counter.subtract(text);
44 }
45 crate::message::Content::Parts(parts) => {
46 for part in parts {
48 if let crate::message::ContentPart::Text { text } = part {
49 counter.subtract(text);
50 }
51 }
52 }
53 }
54 }
55 crate::message::Message::Assistant { content, .. } => {
56 if let Some(content_data) = content {
57 match content_data {
58 crate::message::Content::Text(text) => {
59 counter.subtract(text);
60 }
61 crate::message::Content::Parts(parts) => {
62 for part in parts {
64 if let crate::message::ContentPart::Text { text } = part {
65 counter.subtract(text);
66 }
67 }
68 }
69 }
70 }
71 }
72 crate::message::Message::System { content, .. }
73 | crate::message::Message::Tool { content, .. } => {
74 counter.subtract(content);
75 }
76 }
77 }
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 use crate::message::Message;
86
87 #[test]
88 fn test_drop_oldest_compactor() {
89 let compactor = DropOldestCompactor::default();
90 let mut history = vec![
91 Message::system("System message"),
92 Message::user("First user message"),
93 Message::assistant("First assistant message"),
94 ];
95 let mut counter = TokenCounter::default();
96 counter.observe("System message");
97 counter.observe("First user message");
98 counter.observe("First assistant message");
99
100 assert_eq!(history.len(), 3);
102 assert_eq!(counter.total(), 8); compactor.compact(&mut history, &mut counter, 5);
106
107 assert!(history.len() < 3);
109 assert!(counter.total() <= 5);
110 }
111}