x_ai.rs

  1use anyhow::Result;
  2use serde::{Deserialize, Serialize};
  3use strum::EnumIter;
  4
  5pub const XAI_API_URL: &str = "https://api.x.ai/v1";
  6
  7#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
  8#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, EnumIter)]
  9pub enum Model {
 10    #[serde(rename = "grok-2-vision-latest")]
 11    Grok2Vision,
 12    #[default]
 13    #[serde(rename = "grok-3-latest")]
 14    Grok3,
 15    #[serde(rename = "grok-3-mini-latest")]
 16    Grok3Mini,
 17    #[serde(rename = "grok-3-fast-latest")]
 18    Grok3Fast,
 19    #[serde(rename = "grok-3-mini-fast-latest")]
 20    Grok3MiniFast,
 21    #[serde(rename = "grok-4", alias = "grok-4-latest")]
 22    Grok4,
 23    #[serde(rename = "grok-code-fast-1")]
 24    GrokCodeFast1,
 25    #[serde(rename = "custom")]
 26    Custom {
 27        name: String,
 28        /// The name displayed in the UI, such as in the assistant panel model dropdown menu.
 29        display_name: Option<String>,
 30        max_tokens: u64,
 31        max_output_tokens: Option<u64>,
 32        max_completion_tokens: Option<u64>,
 33    },
 34}
 35
 36impl Model {
 37    pub fn default_fast() -> Self {
 38        Self::Grok3Fast
 39    }
 40
 41    pub fn from_id(id: &str) -> Result<Self> {
 42        match id {
 43            "grok-4" => Ok(Self::Grok4),
 44            "grok-2-vision" => Ok(Self::Grok2Vision),
 45            "grok-3" => Ok(Self::Grok3),
 46            "grok-3-mini" => Ok(Self::Grok3Mini),
 47            "grok-3-fast" => Ok(Self::Grok3Fast),
 48            "grok-3-mini-fast" => Ok(Self::Grok3MiniFast),
 49            "grok-code-fast-1" => Ok(Self::GrokCodeFast1),
 50            _ => anyhow::bail!("invalid model id '{id}'"),
 51        }
 52    }
 53
 54    pub fn id(&self) -> &str {
 55        match self {
 56            Self::Grok2Vision => "grok-2-vision",
 57            Self::Grok3 => "grok-3",
 58            Self::Grok3Mini => "grok-3-mini",
 59            Self::Grok3Fast => "grok-3-fast",
 60            Self::Grok3MiniFast => "grok-3-mini-fast",
 61            Self::Grok4 => "grok-4",
 62            Self::GrokCodeFast1 => "grok-code-fast-1",
 63            Self::Custom { name, .. } => name,
 64        }
 65    }
 66
 67    pub fn display_name(&self) -> &str {
 68        match self {
 69            Self::Grok2Vision => "Grok 2 Vision",
 70            Self::Grok3 => "Grok 3",
 71            Self::Grok3Mini => "Grok 3 Mini",
 72            Self::Grok3Fast => "Grok 3 Fast",
 73            Self::Grok3MiniFast => "Grok 3 Mini Fast",
 74            Self::Grok4 => "Grok 4",
 75            Self::GrokCodeFast1 => "Grok Code Fast 1",
 76            Self::Custom {
 77                name, display_name, ..
 78            } => display_name.as_ref().unwrap_or(name),
 79        }
 80    }
 81
 82    pub fn max_token_count(&self) -> u64 {
 83        match self {
 84            Self::Grok3 | Self::Grok3Mini | Self::Grok3Fast | Self::Grok3MiniFast => 131_072,
 85            Self::Grok4 | Self::GrokCodeFast1 => 256_000,
 86            Self::Grok2Vision => 8_192,
 87            Self::Custom { max_tokens, .. } => *max_tokens,
 88        }
 89    }
 90
 91    pub fn max_output_tokens(&self) -> Option<u64> {
 92        match self {
 93            Self::Grok3 | Self::Grok3Mini | Self::Grok3Fast | Self::Grok3MiniFast => Some(8_192),
 94            Self::Grok4 | Self::GrokCodeFast1 => Some(64_000),
 95            Self::Grok2Vision => Some(4_096),
 96            Self::Custom {
 97                max_output_tokens, ..
 98            } => *max_output_tokens,
 99        }
100    }
101
102    pub fn supports_parallel_tool_calls(&self) -> bool {
103        match self {
104            Self::Grok2Vision
105            | Self::Grok3
106            | Self::Grok3Mini
107            | Self::Grok3Fast
108            | Self::Grok3MiniFast
109            | Self::Grok4 => true,
110            Self::GrokCodeFast1 | Model::Custom { .. } => false,
111        }
112    }
113
114    pub fn supports_prompt_cache_key(&self) -> bool {
115        false
116    }
117
118    pub fn supports_tool(&self) -> bool {
119        match self {
120            Self::Grok2Vision
121            | Self::Grok3
122            | Self::Grok3Mini
123            | Self::Grok3Fast
124            | Self::Grok3MiniFast
125            | Self::Grok4
126            | Self::GrokCodeFast1 => true,
127            Model::Custom { .. } => false,
128        }
129    }
130
131    pub fn supports_images(&self) -> bool {
132        matches!(self, Self::Grok2Vision)
133    }
134}