#[ cfg( feature = "chat" ) ]
use super::super::Client;
#[ cfg( feature = "chat" ) ]
#[ derive( Debug ) ]
pub struct ConversationBuilder< 'a >
{
pub( crate ) client : &'a Client,
pub( crate ) messages : Vec< crate::models::ChatMessage >,
pub( crate ) model : String,
pub( crate ) temperature : Option< f32 >,
pub( crate ) max_tokens : Option< i32 >,
pub( crate ) top_p : Option< f32 >,
}
#[ cfg( feature = "chat" ) ]
impl ConversationBuilder< '_ >
{
#[ inline ]
#[ must_use ]
pub fn system( mut self, content : &str ) -> Self
{
assert!( !self.messages.iter().any( | msg | msg.role == "system" ),
"Only one system message is allowed per conversation. Use a single system() call." );
assert!( !content.is_empty(), "System message content cannot be empty." );
self.messages.push( crate::models::ChatMessage
{
role : "system".to_string(),
content : content.to_string(),
} );
self
}
#[ inline ]
#[ must_use ]
pub fn user( mut self, content : &str ) -> Self
{
assert!( !content.is_empty(), "User message content cannot be empty." );
self.messages.push( crate::models::ChatMessage
{
role : "user".to_string(),
content : content.to_string(),
} );
self
}
#[ inline ]
#[ must_use ]
pub fn assistant( mut self, content : &str ) -> Self
{
assert!( !content.is_empty(), "Assistant message content cannot be empty." );
self.messages.push( crate::models::ChatMessage
{
role : "assistant".to_string(),
content : content.to_string(),
} );
self
}
#[ inline ]
#[ must_use ]
pub fn model( mut self, model : &str ) -> Self
{
assert!( !model.is_empty(), "Model name cannot be empty." );
self.model = model.to_string();
self
}
#[ inline ]
#[ must_use ]
pub fn temperature( mut self, temperature : f32 ) -> Self
{
assert!( ( 0.0..=2.0 ).contains( &temperature ), "Temperature must be between 0.0 and 2.0, got : {temperature}" );
self.temperature = Some( temperature );
self
}
#[ inline ]
#[ must_use ]
pub fn max_tokens( mut self, max_tokens : i32 ) -> Self
{
assert!( max_tokens > 0, "max_tokens must be positive, got : {max_tokens}" );
self.max_tokens = Some( max_tokens );
self
}
#[ inline ]
#[ must_use ]
pub fn top_p( mut self, top_p : f32 ) -> Self
{
assert!( ( 0.0..=1.0 ).contains( &top_p ), "top_p must be between 0.0 and 1.0, got : {top_p}" );
self.top_p = Some( top_p );
self
}
#[ inline ]
pub async fn complete( self ) -> Result< crate::models::ChatCompletionResponse, crate::error::Error >
{
let request = crate::models::ChatCompletionRequest
{
messages : self.messages,
model : self.model,
temperature : self.temperature,
max_tokens : self.max_tokens,
top_p : self.top_p,
..Default::default()
};
self.client.chat().complete( &request ).await
}
#[ must_use ]
#[ inline ]
pub fn build_request( self ) -> crate::models::ChatCompletionRequest
{
crate ::models::ChatCompletionRequest
{
messages : self.messages,
model : self.model,
temperature : self.temperature,
max_tokens : self.max_tokens,
top_p : self.top_p,
..Default::default()
}
}
#[ must_use ]
#[ inline ]
pub fn summary( &self ) -> ConversationSummary
{
let message_counts = self.messages.iter().fold(
( 0, 0, 0 ),
| ( mut system, mut user, mut assistant ), msg | {
match msg.role.as_str()
{
"system" => system += 1,
"user" => user += 1,
"assistant" => assistant += 1,
_ => {},
}
( system, user, assistant )
}
);
ConversationSummary
{
total_messages : self.messages.len(),
system_messages : message_counts.0,
user_messages : message_counts.1,
assistant_messages : message_counts.2,
model : self.model.clone(),
has_temperature : self.temperature.is_some(),
has_max_tokens : self.max_tokens.is_some(),
has_top_p : self.top_p.is_some(),
}
}
}
#[ cfg( feature = "chat" ) ]
#[ derive( Debug, Clone ) ]
pub struct ConversationSummary
{
pub total_messages : usize,
pub system_messages : usize,
pub user_messages : usize,
pub assistant_messages : usize,
pub model : String,
pub has_temperature : bool,
pub has_max_tokens : bool,
pub has_top_p : bool,
}