#[derive(Debug, Clone)]
pub enum LlmType {
GEMINI,
GPT
}
pub type Triple = (usize, usize, usize);
impl std::fmt::Display for LlmType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
LlmType::GEMINI => write!(f, "GEMINI"),
LlmType::GPT => write!(f, "GPT"),
}
}
}
#[derive(Debug, Clone)]
pub struct LlmReturn {
pub llm_type: LlmType,
pub text: String,
pub finish_reason: String,
pub usage: Triple,
pub timing: f64,
pub citations: Option<String>,
pub safety_ratings: Option<Vec<String>>,
}
impl LlmReturn {
pub fn new(llm_type: LlmType, text: String, finish_reason: String, usage: Triple, timing: f64, citations: Option<String>, safety_ratings: Option<Vec<String>>) -> Self {
LlmReturn { llm_type, text, finish_reason, usage, timing, citations, safety_ratings }
}
}
impl std::fmt::Display for LlmReturn {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
println!("---------- {} ----------", self.llm_type);
let _ = writeln!(f, "{}", self.text);
if !self.finish_reason.is_empty() && self.finish_reason != "STOP" {
let _ = println!("Finish Reason: {}", self.finish_reason);
}
println!("Tokens: Input: {} + Output: {} -> Total: {}",
self.usage.0, self.usage.1, self.usage.2);
println!("Timing: {}", self.timing);
if let Some(ref citations) = self.citations {
println!("Citations:\n{}", citations);
}
if let Some(ref safety_ratings) = self.safety_ratings {
println!("Safety Settings: {:?}", safety_ratings);
}
Ok(())
}
}
#[derive(Debug)]
pub struct Message {
pub role: String,
pub text: String
}
pub trait LlmMessage {
fn summarize(&self) -> String;
}
impl LlmMessage for Message {
fn summarize(&self) -> String {
"Message".to_string()
}
}
impl Message {
/// Supply single role and single part text
pub fn text(role: &str, text: &str) -> Self {
Self { role: role.into(), text: text.into() }
}
/// Supply single role with multi-string for iparts with single text
pub fn many_text(role: &str, prompt: &[String]) -> Self {
let prompt: String =
prompt.iter()
.fold(String::new(), |mut s, p| {
s.push_str(if s.is_empty() { "" } else { "\n" });
s.push_str(p);
s
});
Self { role: role.into(), text: prompt }
}
/// Supply simple, 'system' text
pub fn system(system_prompt: &str) -> Vec<Self> {
vec![Self::text("system", system_prompt)]
}
/// Supply multi-parts and single 'system' text
pub fn multi_part_system(system_prompts: &[String]) -> Vec<Self> {
vec![Self::many_text("system", system_prompts)]
}
/// Supply multi-context 'system' text
pub fn systems(system_prompts: &[String]) -> Vec<Self> {
system_prompts.iter()
.map(|sp| Self::text("system", &sp))
.collect()
}
/// Supply multi-String text with user and model alternating
pub fn dialogue(prompts: &[String]) -> Vec<Self> {
prompts.iter()
.enumerate()
.map(|(i, p)| {
let role = if i % 2 == 0 { "user" } else { "llm" };
Self::text(role, p)
})
.collect()
}
}