Add support for OpenAI o3 and o4-mini models (#28881)

Umesh Yadav and Peter Tripp created

Release Notes:

- Add support for OpenAI o3 and o4-mini models via OpenAI API and
Copilot Chat providers.

---------

Co-authored-by: Peter Tripp <peter@zed.dev>

Change summary

crates/copilot/src/copilot_chat.rs                  | 16 ++++++++++++++
crates/language_model/src/model/cloud_model.rs      |  2 +
crates/language_models/src/provider/copilot_chat.rs |  5 +++
crates/open_ai/src/open_ai.rs                       | 12 +++++++++++
4 files changed, 33 insertions(+), 2 deletions(-)

Detailed changes

crates/copilot/src/copilot_chat.rs 🔗

@@ -41,6 +41,10 @@ pub enum Model {
     O1,
     #[serde(alias = "o1-mini", rename = "o3-mini")]
     O3Mini,
+    #[serde(alias = "o3", rename = "o3")]
+    O3,
+    #[serde(alias = "o4-mini", rename = "o4-mini")]
+    O4Mini,
     #[serde(alias = "claude-3-5-sonnet", rename = "claude-3.5-sonnet")]
     Claude3_5Sonnet,
     #[serde(alias = "claude-3-7-sonnet", rename = "claude-3.7-sonnet")]
@@ -63,6 +67,8 @@ impl Model {
             | Self::Gpt4
             | Self::Gpt4_1
             | Self::Gpt3_5Turbo
+            | Self::O3
+            | Self::O4Mini
             | Self::Claude3_5Sonnet
             | Self::Claude3_7Sonnet
             | Self::Claude3_7SonnetThinking => true,
@@ -78,6 +84,8 @@ impl Model {
             "gpt-3.5-turbo" => Ok(Self::Gpt3_5Turbo),
             "o1" => Ok(Self::O1),
             "o3-mini" => Ok(Self::O3Mini),
+            "o3" => Ok(Self::O3),
+            "o4-mini" => Ok(Self::O4Mini),
             "claude-3-5-sonnet" => Ok(Self::Claude3_5Sonnet),
             "claude-3-7-sonnet" => Ok(Self::Claude3_7Sonnet),
             "claude-3.7-sonnet-thought" => Ok(Self::Claude3_7SonnetThinking),
@@ -95,6 +103,8 @@ impl Model {
             Self::Gpt4o => "gpt-4o",
             Self::O3Mini => "o3-mini",
             Self::O1 => "o1",
+            Self::O3 => "o3",
+            Self::O4Mini => "o4-mini",
             Self::Claude3_5Sonnet => "claude-3-5-sonnet",
             Self::Claude3_7Sonnet => "claude-3-7-sonnet",
             Self::Claude3_7SonnetThinking => "claude-3.7-sonnet-thought",
@@ -111,6 +121,8 @@ impl Model {
             Self::Gpt4o => "GPT-4o",
             Self::O3Mini => "o3-mini",
             Self::O1 => "o1",
+            Self::O3 => "o3",
+            Self::O4Mini => "o4-mini",
             Self::Claude3_5Sonnet => "Claude 3.5 Sonnet",
             Self::Claude3_7Sonnet => "Claude 3.7 Sonnet",
             Self::Claude3_7SonnetThinking => "Claude 3.7 Sonnet Thinking",
@@ -123,10 +135,12 @@ impl Model {
         match self {
             Self::Gpt4o => 64_000,
             Self::Gpt4 => 32_768,
-            Self::Gpt4_1 => 1_047_576,
+            Self::Gpt4_1 => 128_000,
             Self::Gpt3_5Turbo => 12_288,
             Self::O3Mini => 64_000,
             Self::O1 => 20_000,
+            Self::O3 => 128_000,
+            Self::O4Mini => 128_000,
             Self::Claude3_5Sonnet => 200_000,
             Self::Claude3_7Sonnet => 90_000,
             Self::Claude3_7SonnetThinking => 90_000,

crates/language_model/src/model/cloud_model.rs 🔗

@@ -90,6 +90,8 @@ impl CloudModel {
                 | open_ai::Model::O1Preview
                 | open_ai::Model::O1
                 | open_ai::Model::O3Mini
+                | open_ai::Model::O3
+                | open_ai::Model::O4Mini
                 | open_ai::Model::Custom { .. } => {
                     LanguageModelAvailability::RequiresPlan(Plan::ZedPro)
                 }

crates/language_models/src/provider/copilot_chat.rs 🔗

@@ -219,7 +219,10 @@ impl LanguageModel for CopilotChatLanguageModel {
                     CopilotChatModel::Gpt4 => open_ai::Model::Four,
                     CopilotChatModel::Gpt4_1 => open_ai::Model::FourPointOne,
                     CopilotChatModel::Gpt3_5Turbo => open_ai::Model::ThreePointFiveTurbo,
-                    CopilotChatModel::O1 | CopilotChatModel::O3Mini => open_ai::Model::Four,
+                    CopilotChatModel::O1 => open_ai::Model::O1,
+                    CopilotChatModel::O3Mini => open_ai::Model::O3Mini,
+                    CopilotChatModel::O3 => open_ai::Model::O3,
+                    CopilotChatModel::O4Mini => open_ai::Model::O4Mini,
                     CopilotChatModel::Claude3_5Sonnet
                     | CopilotChatModel::Claude3_7Sonnet
                     | CopilotChatModel::Claude3_7SonnetThinking

crates/open_ai/src/open_ai.rs 🔗

@@ -85,6 +85,10 @@ pub enum Model {
     O1Mini,
     #[serde(rename = "o3-mini", alias = "o3-mini")]
     O3Mini,
+    #[serde(rename = "o3", alias = "o3")]
+    O3,
+    #[serde(rename = "o4-mini", alias = "o4-mini")]
+    O4Mini,
 
     #[serde(rename = "custom")]
     Custom {
@@ -112,6 +116,8 @@ impl Model {
             "o1-preview" => Ok(Self::O1Preview),
             "o1-mini" => Ok(Self::O1Mini),
             "o3-mini" => Ok(Self::O3Mini),
+            "o3" => Ok(Self::O3),
+            "o4-mini" => Ok(Self::O4Mini),
             _ => Err(anyhow!("invalid model id")),
         }
     }
@@ -130,6 +136,8 @@ impl Model {
             Self::O1Preview => "o1-preview",
             Self::O1Mini => "o1-mini",
             Self::O3Mini => "o3-mini",
+            Self::O3 => "o3",
+            Self::O4Mini => "o4-mini",
             Self::Custom { name, .. } => name,
         }
     }
@@ -148,6 +156,8 @@ impl Model {
             Self::O1Preview => "o1-preview",
             Self::O1Mini => "o1-mini",
             Self::O3Mini => "o3-mini",
+            Self::O3 => "o3",
+            Self::O4Mini => "o4-mini",
             Self::Custom {
                 name, display_name, ..
             } => display_name.as_ref().unwrap_or(name),
@@ -168,6 +178,8 @@ impl Model {
             Self::O1Preview => 128_000,
             Self::O1Mini => 128_000,
             Self::O3Mini => 200_000,
+            Self::O3 => 200_000,
+            Self::O4Mini => 200_000,
             Self::Custom { max_tokens, .. } => *max_tokens,
         }
     }