yammer 0.16.0

yammer provides an ollama-compatible client library.
Documentation
use reqwest::RequestBuilder;

////////////////////////////////////////// GenerateRequest /////////////////////////////////////////

/// Generate a response to a prompt.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct GenerateRequest {
    /// The name of the ollama model to use from the ollama library.
    pub model: String,

    /// The prompt to provide to the model.  This is the text that the model will use to generate a
    /// response.
    pub prompt: String,

    /// The suffix to append to the prompt.  This is useful for generating a response that is a
    /// continuation of the prompt.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub suffix: Option<String>,

    /// A list of base64-encoded images to supply to the model.
    pub images: Option<Vec<String>>,

    /// The format to return the response in.  If provided, this must be "json".
    #[serde(skip_serializing_if = "Option::is_none")]
    pub format: Option<serde_json::Value>,

    /// The system to use for the response.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub system: Option<String>,

    /// The template to use for the response.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub template: Option<String>,

    /// Should this response stream?
    #[serde(skip_serializing_if = "Option::is_none")]
    pub stream: Option<bool>,

    /// Should this response be raw?
    #[serde(skip_serializing_if = "Option::is_none")]
    pub raw: Option<bool>,

    /// How long to hold the model in memory for once the request completes.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub keep_alive: Option<String>,

    /// Additional options to pass to the model.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub options: Option<serde_json::Value>,
}

impl Default for GenerateRequest {
    fn default() -> Self {
        Self {
            model: "gemma2".to_string(),
            prompt: "42".to_string(),
            suffix: None,
            images: None,
            format: None,
            system: None,
            template: None,
            stream: None,
            raw: None,
            keep_alive: None,
            options: Some(serde_json::json!({ "num_ctx": 12288 })),
        }
    }
}

impl GenerateRequest {
    /// Create a new RequestBuilder for this generate request.
    pub fn make_request(&self, ollama_host: &str) -> RequestBuilder {
        reqwest::Client::new()
            .post(format!("{}/api/generate", ollama_host))
            .json(self)
    }
}

///////////////////////////////////////// GenerateResponse /////////////////////////////////////////

/// A response to a generate request.
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct GenerateResponse {
    /// The name of the model used to generate the response.
    pub model: String,
    /// The time the response was created.
    pub created_at: String,
    /// The response generated by the model.
    pub response: String,
    /// Whether the response is done.
    pub done: bool,
    /// Why the response is done.
    pub done_reason: Option<String>,
    /// The duration of the response.
    pub total_duration: Option<f64>,
    /// The duration of loading the model.
    pub load_duration: Option<f64>,
    /// The number of tokens counted in the prompt.
    pub prompt_eval_count: Option<f64>,
    /// The duration of the prompt evaluation.
    pub prompt_eval_duration: Option<f64>,
    /// The number of tokens counted in the response.
    pub eval_count: Option<f64>,
    /// The duration of the response evaluation.
    pub eval_duration: Option<f64>,
    /// The context for a future generate call.
    pub context: Option<Vec<f64>>,
}

//////////////////////////////////////////// ChatMessage ///////////////////////////////////////////

/// A message sent or received in a chat.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct ChatMessage {
    /// The role of the message sender.
    pub role: String,
    /// The content of the message.
    pub content: String,
    /// The images attached to the message.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub images: Option<Vec<String>>,
    /// The tool calls made by the message.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tool_calls: Option<Vec<serde_json::Value>>,
}

//////////////////////////////////////////// ChatRequest ///////////////////////////////////////////

/// A request to chat with a model.
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct ChatRequest {
    /// The name of the ollama model to use from the ollama library.
    pub model: String,
    /// The chat messages to send to the model.
    pub messages: Vec<ChatMessage>,
    /// The tools available to use in the chat.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tools: Option<serde_json::Value>,
    /// The format to return the response in.  If provided, this must be "json".
    #[serde(skip_serializing_if = "Option::is_none")]
    pub format: Option<serde_json::Value>,
    /// Should this response stream?
    #[serde(skip_serializing_if = "Option::is_none")]
    pub stream: Option<bool>,
    /// How long to keep the model alive for after the request completes.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub keep_alive: Option<String>,
    /// Additional options to pass to the model.
    pub options: serde_json::Value,
}

impl ChatRequest {
    /// Create a new RequestBuilder for this chat request.
    pub fn make_request(&self, ollama_host: &str) -> RequestBuilder {
        reqwest::Client::new()
            .post(format!("{}/api/chat", ollama_host))
            .json(self)
    }
}

/////////////////////////////////////////// ChatResponse ///////////////////////////////////////////

/// A response to a chat request.
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct ChatResponse {
    /// The name of the model used to generate the response.
    pub model: String,
    /// When the response was created.
    pub created_at: String,
    /// The messages generated by the model.
    pub message: ChatMessage,
    /// Whether the response is done.
    pub done: bool,
    /// The duration of the response.
    pub total_duration: Option<f64>,
    /// The duration of loading the model.
    pub load_duration: Option<f64>,
    /// The number of tokens counted in the prompt.
    pub prompt_eval_count: Option<f64>,
    /// The duration of the prompt evaluation.
    pub prompt_eval_duration: Option<f64>,
    /// The number of tokens counted in the response.
    pub eval_count: Option<f64>,
    /// The duration of the response evaluation.
    pub eval_duration: Option<f64>,
}

/////////////////////////////////////////// EmbedRequest ///////////////////////////////////////////

/// A request to embed multiple input documents.
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct EmbedRequest {
    /// The name of the model to use for embedding.
    pub model: String,
    /// The input texts to embed.
    pub input: Vec<String>,
}

impl EmbedRequest {
    /// Create a new RequestBuilder for this embed request.
    pub fn make_request(&self, ollama_host: &str) -> RequestBuilder {
        reqwest::Client::new()
            .post(format!("{}/api/embed", ollama_host))
            .json(self)
    }
}

/////////////////////////////////////////// EmbedResponse //////////////////////////////////////////

/// A response to an embed response.
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct EmbedResponse {
    /// The name of the model used to generate the response.
    pub model: String,
    /// The embeddings of the input, in the same order.
    pub embeddings: Vec<Vec<f32>>,
    /// The duration of the response.
    pub total_duration: Option<f64>,
    /// The duration of loading the model.
    pub load_duration: Option<f64>,
    /// The number of tokens counted in the prompt.
    pub prompt_eval_count: Option<f64>,
}