use serde::{ Deserialize, Serialize };
use super::input::InferenceParameters;
use super::output::InferenceOutput;
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct ChatMessage
{
pub role : String,
pub content : String,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub tool_calls : Option< Vec< ToolCall > >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub tool_call_id : Option< String >,
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct ToolCall
{
pub id : String,
#[ serde( rename = "type" ) ]
pub tool_type : String,
pub function : FunctionCall,
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct FunctionCall
{
pub name : String,
pub arguments : String,
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct ChatCompletionRequest
{
pub messages : Vec< ChatMessage >,
pub model : String,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub temperature : Option< f32 >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub max_tokens : Option< u32 >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub top_p : Option< f32 >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub stream : Option< bool >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub tools : Option< Vec< ToolDefinition > >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub tool_choice : Option< String >,
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct ToolDefinition
{
#[ serde( rename = "type" ) ]
pub tool_type : String,
pub function : crate::components::tools::Tool,
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct ChatCompletionResponse
{
pub id : String,
pub object : String,
pub created : i64,
pub model : String,
pub choices : Vec< ChatChoice >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub usage : Option< ChatUsage >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub system_fingerprint : Option< String >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub service_tier : Option< String >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub usage_breakdown : Option< serde_json::Value >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub x_groq : Option< serde_json::Value >,
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct ChatChoice
{
pub index : u32,
pub message : ChatMessage,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub finish_reason : Option< String >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub logprobs : Option< serde_json::Value >,
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct ChatUsage
{
pub prompt_tokens : u32,
pub completion_tokens : u32,
pub total_tokens : u32,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub queue_time : Option< f64 >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub prompt_time : Option< f64 >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub completion_time : Option< f64 >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub total_time : Option< f64 >,
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct InferenceRequest
{
pub inputs : String,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub parameters : Option< InferenceParameters >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub options : Option< InferenceOptions >,
}
impl InferenceRequest
{
#[ inline ]
#[ must_use ]
pub fn new( inputs : impl Into< String > ) -> Self
{
Self
{
inputs : inputs.into(),
parameters : None,
options : None,
}
}
#[ inline ]
#[ must_use ]
pub fn with_parameters( mut self, parameters : InferenceParameters ) -> Self
{
self.parameters = Some( parameters );
self
}
#[ inline ]
#[ must_use ]
pub fn with_options( mut self, options : InferenceOptions ) -> Self
{
self.options = Some( options );
self
}
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct BatchInferenceRequest
{
pub inputs : Vec< String >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub parameters : Option< InferenceParameters >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub options : Option< InferenceOptions >,
}
impl BatchInferenceRequest
{
#[ inline ]
#[ must_use ]
pub fn new( inputs : Vec< String > ) -> Self
{
Self
{
inputs,
parameters : None,
options : None,
}
}
#[ inline ]
#[ must_use ]
pub fn with_parameters( mut self, parameters : InferenceParameters ) -> Self
{
self.parameters = Some( parameters );
self
}
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct InferenceOptions
{
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub use_cache : Option< bool >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub wait_for_model : Option< bool >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub use_gpu : Option< bool >,
}
impl Default for InferenceOptions
{
#[ inline ]
fn default() -> Self
{
Self::recommended()
}
}
impl InferenceOptions
{
#[ inline ]
#[ must_use ]
pub fn recommended() -> Self
{
Self
{
use_cache : Some( true ), wait_for_model : Some( true ), use_gpu : Some( true ), }
}
#[ inline ]
#[ must_use ]
pub fn new() -> Self
{
Self::recommended()
}
#[ inline ]
#[ must_use ]
pub fn empty() -> Self
{
Self
{
use_cache : None,
wait_for_model : None,
use_gpu : None,
}
}
#[ inline ]
#[ must_use ]
pub fn conservative() -> Self
{
Self
{
use_cache : Some( false ), wait_for_model : Some( false ), use_gpu : Some( false ), }
}
#[ inline ]
#[ must_use ]
pub fn with_use_cache( mut self, use_cache : bool ) -> Self
{
self.use_cache = Some( use_cache );
self
}
#[ inline ]
#[ must_use ]
pub fn with_wait_for_model( mut self, wait_for_model : bool ) -> Self
{
self.wait_for_model = Some( wait_for_model );
self
}
#[ inline ]
#[ must_use ]
pub fn with_use_gpu( mut self, use_gpu : bool ) -> Self
{
self.use_gpu = Some( use_gpu );
self
}
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
#[ serde( untagged ) ]
pub enum InferenceResponse
{
Single( InferenceOutput ),
Batch( Vec< InferenceOutput > ),
Summarization( Vec< SummarizationOutput > ),
}
#[ derive( Debug, Clone, Serialize, Deserialize ) ]
pub struct SummarizationOutput
{
pub summary_text : String,
}
impl InferenceResponse
{
#[ inline ]
#[ must_use ]
pub fn extract_text( &self ) -> Option< String >
{
match self
{
Self::Single( output ) => Some( output.generated_text.clone() ),
Self::Batch( outputs ) => outputs.first().map( | o | o.generated_text.clone() ),
Self::Summarization( summaries ) => summaries.first().map( | s | s.summary_text.clone() ),
}
}
#[ inline ]
#[ must_use ]
pub fn extract_text_or_default( &self, default : &str ) -> String
{
self.extract_text().unwrap_or_else( || default.to_string() )
}
}