use alloc::{string::String, vec::Vec};
use crate::{
LanguageModel,
llm::{Message, Tool, model::Parameters, tool::Tools, try_collect},
};
#[derive(Debug)]
pub struct Assistant<LLM: LanguageModel> {
messages: Vec<Message>,
tools: Tools,
llm: LLM,
}
impl<LLM: LanguageModel> Assistant<LLM> {
#[must_use]
pub const fn new(llm: LLM) -> Self {
Self {
messages: Vec::new(),
tools: Tools::new(),
llm,
}
}
#[must_use]
pub fn system(mut self, prompt: impl Into<String>) -> Self {
self.messages.push(Message::system(prompt.into()));
self
}
#[must_use]
pub fn tool(mut self, tool: impl Tool) -> Self {
self.tools.register(tool);
self
}
pub async fn send(&mut self, message: impl Into<String>) -> anyhow::Result<()> {
self.messages.push(Message::user(message));
let binding = Parameters::default();
let stream = self.llm.respond(&self.messages, &mut self.tools, &binding);
let response = try_collect(stream).await?;
self.messages.push(Message::assistant(response));
Ok(())
}
pub const fn messages(&self) -> &[Message] {
self.messages.as_slice()
}
}