use std::sync::Arc;
use rig_core::completion::Message;
use rig_core::conversation::pairing::safe_start;
use rig_core::wasm_compat::{WasmCompatSend, WasmCompatSync};
use crate::{HeuristicTokenCounter, TokenCounter};
pub trait Recent: WasmCompatSend + WasmCompatSync {
fn start(&self, messages: &[Arc<Message>]) -> usize;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct LastMessages(pub usize);
impl Recent for LastMessages {
fn start(&self, messages: &[Arc<Message>]) -> usize {
messages.len().saturating_sub(self.0)
}
}
#[derive(Clone, Copy, Debug)]
pub struct TokenBudget<C: TokenCounter = HeuristicTokenCounter> {
pub max_tokens: usize,
pub counter: C,
}
impl TokenBudget {
pub fn new(max_tokens: usize) -> Self {
Self {
max_tokens,
counter: HeuristicTokenCounter::default(),
}
}
}
impl<C: TokenCounter> Recent for TokenBudget<C> {
fn start(&self, messages: &[Arc<Message>]) -> usize {
let mut budget = self.max_tokens;
let mut start = messages.len();
for (index, message) in messages.iter().enumerate().rev() {
let cost = self.counter.count(message);
if cost > budget {
break;
}
budget -= cost;
start = index;
}
start
}
}
pub fn view<'m>(messages: &'m [Arc<Message>], recent: &dyn Recent) -> &'m [Arc<Message>] {
let start = safe_start(messages, recent.start(messages));
messages.get(start..).unwrap_or_default()
}
#[cfg(test)]
mod tests;