pub mod compaction;
pub mod state;
pub mod tokenizer;
pub mod types;
use std::sync::Arc;
use crate::config::MemorySettings;
use crate::error::Result;
use crate::memory::compaction::Compactor;
use crate::memory::state::ConversationStateAccess;
use crate::memory::tokenizer::TokenCounter;
use crate::memory::types::CompactionReport;
pub struct MemoryManager {
token_counter: TokenCounter,
compactor: Compactor,
context_token_limit: usize,
}
impl MemoryManager {
pub fn new(
settings: &MemorySettings,
cascade_config: Arc<llm_cascade::AppConfig>,
db_conn: rusqlite::Connection,
) -> Result<Self> {
let token_counter = TokenCounter::new(&settings.tokenizer_model)?;
let compactor = Compactor::new(settings, cascade_config, db_conn);
Ok(Self {
token_counter,
compactor,
context_token_limit: settings.context_token_limit,
})
}
pub fn count_tokens(&self, state: &impl ConversationStateAccess) -> usize {
self.token_counter.count_messages(state.messages())
}
pub fn should_compact(&self, token_count: usize) -> bool {
token_count > self.context_token_limit
}
pub async fn compact(
&self,
state: &mut impl ConversationStateAccess,
) -> Result<CompactionReport> {
let tokens = self.count_tokens(state);
if !self.should_compact(tokens) {
return Ok(CompactionReport {
messages_before: state.messages().len(),
messages_after: state.messages().len(),
tokens_before: tokens,
tokens_after: tokens,
});
}
self.compactor
.compact(state, &self.token_counter, self.context_token_limit)
.await
}
pub fn token_limit(&self) -> usize {
self.context_token_limit
}
pub fn token_counter(&self) -> &TokenCounter {
&self.token_counter
}
}