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-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-2-vision" => Ok(Self::Grok2Vision),
 44            "grok-3" => Ok(Self::Grok3),
 45            "grok-3-mini" => Ok(Self::Grok3Mini),
 46            "grok-3-fast" => Ok(Self::Grok3Fast),
 47            "grok-3-mini-fast" => Ok(Self::Grok3MiniFast),
 48            "grok-code-fast-1" => Ok(Self::GrokCodeFast1),
 49            _ => anyhow::bail!("invalid model id '{id}'"),
 50        }
 51    }
 52
 53    pub fn id(&self) -> &str {
 54        match self {
 55            Self::Grok2Vision => "grok-2-vision",
 56            Self::Grok3 => "grok-3",
 57            Self::Grok3Mini => "grok-3-mini",
 58            Self::Grok3Fast => "grok-3-fast",
 59            Self::Grok3MiniFast => "grok-3-mini-fast",
 60            Self::Grok4 => "grok-4",
 61            Self::GrokCodeFast1 => "grok-code-fast-1",
 62            Self::Custom { name, .. } => name,
 63        }
 64    }
 65
 66    pub fn display_name(&self) -> &str {
 67        match self {
 68            Self::Grok2Vision => "Grok 2 Vision",
 69            Self::Grok3 => "Grok 3",
 70            Self::Grok3Mini => "Grok 3 Mini",
 71            Self::Grok3Fast => "Grok 3 Fast",
 72            Self::Grok3MiniFast => "Grok 3 Mini Fast",
 73            Self::Grok4 => "Grok 4",
 74            Self::GrokCodeFast1 => "Grok Code Fast 1",
 75            Self::Custom {
 76                name, display_name, ..
 77            } => display_name.as_ref().unwrap_or(name),
 78        }
 79    }
 80
 81    pub fn max_token_count(&self) -> u64 {
 82        match self {
 83            Self::Grok3 | Self::Grok3Mini | Self::Grok3Fast | Self::Grok3MiniFast => 131_072,
 84            Self::Grok4 | Self::GrokCodeFast1 => 256_000,
 85            Self::Grok2Vision => 8_192,
 86            Self::Custom { max_tokens, .. } => *max_tokens,
 87        }
 88    }
 89
 90    pub fn max_output_tokens(&self) -> Option<u64> {
 91        match self {
 92            Self::Grok3 | Self::Grok3Mini | Self::Grok3Fast | Self::Grok3MiniFast => Some(8_192),
 93            Self::Grok4 | Self::GrokCodeFast1 => Some(64_000),
 94            Self::Grok2Vision => Some(4_096),
 95            Self::Custom {
 96                max_output_tokens, ..
 97            } => *max_output_tokens,
 98        }
 99    }
100
101    pub fn supports_parallel_tool_calls(&self) -> bool {
102        match self {
103            Self::Grok2Vision
104            | Self::Grok3
105            | Self::Grok3Mini
106            | Self::Grok3Fast
107            | Self::Grok3MiniFast
108            | Self::Grok4 => true,
109            Self::GrokCodeFast1 | Model::Custom { .. } => false,
110        }
111    }
112
113    pub fn supports_prompt_cache_key(&self) -> bool {
114        false
115    }
116
117    pub fn supports_tool(&self) -> bool {
118        match self {
119            Self::Grok2Vision
120            | Self::Grok3
121            | Self::Grok3Mini
122            | Self::Grok3Fast
123            | Self::Grok3MiniFast
124            | Self::Grok4
125            | Self::GrokCodeFast1 => true,
126            Model::Custom { .. } => false,
127        }
128    }
129
130    pub fn supports_images(&self) -> bool {
131        matches!(self, Self::Grok2Vision)
132    }
133}