1use ai::providers::open_ai::{
2 AzureOpenAiApiVersion, OpenAiCompletionProviderKind, OPEN_AI_API_URL,
3};
4use anyhow::anyhow;
5use gpui::Pixels;
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8use settings::Settings;
9
10#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
11#[serde(rename_all = "snake_case")]
12pub enum OpenAiModel {
13 #[serde(rename = "gpt-3.5-turbo-0613")]
14 ThreePointFiveTurbo,
15 #[serde(rename = "gpt-4-0613")]
16 Four,
17 #[serde(rename = "gpt-4-1106-preview")]
18 FourTurbo,
19}
20
21impl OpenAiModel {
22 pub fn full_name(&self) -> &'static str {
23 match self {
24 Self::ThreePointFiveTurbo => "gpt-3.5-turbo-0613",
25 Self::Four => "gpt-4-0613",
26 Self::FourTurbo => "gpt-4-1106-preview",
27 }
28 }
29
30 pub fn short_name(&self) -> &'static str {
31 match self {
32 Self::ThreePointFiveTurbo => "gpt-3.5-turbo",
33 Self::Four => "gpt-4",
34 Self::FourTurbo => "gpt-4-turbo",
35 }
36 }
37
38 pub fn cycle(&self) -> Self {
39 match self {
40 Self::ThreePointFiveTurbo => Self::Four,
41 Self::Four => Self::FourTurbo,
42 Self::FourTurbo => Self::ThreePointFiveTurbo,
43 }
44 }
45}
46
47#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
48#[serde(rename_all = "snake_case")]
49pub enum AssistantDockPosition {
50 Left,
51 Right,
52 Bottom,
53}
54
55#[derive(Debug, Deserialize)]
56pub struct AssistantSettings {
57 /// Whether to show the assistant panel button in the status bar.
58 pub button: bool,
59 /// Where to dock the assistant.
60 pub dock: AssistantDockPosition,
61 /// Default width in pixels when the assistant is docked to the left or right.
62 pub default_width: Pixels,
63 /// Default height in pixels when the assistant is docked to the bottom.
64 pub default_height: Pixels,
65 /// The default OpenAI model to use when starting new conversations.
66 #[deprecated = "Please use `provider.default_model` instead."]
67 pub default_open_ai_model: OpenAiModel,
68 /// OpenAI API base URL to use when starting new conversations.
69 #[deprecated = "Please use `provider.api_url` instead."]
70 pub openai_api_url: String,
71 /// The settings for the AI provider.
72 pub provider: AiProviderSettings,
73}
74
75impl AssistantSettings {
76 pub fn provider_kind(&self) -> anyhow::Result<OpenAiCompletionProviderKind> {
77 match &self.provider {
78 AiProviderSettings::OpenAi(_) => Ok(OpenAiCompletionProviderKind::OpenAi),
79 AiProviderSettings::AzureOpenAi(settings) => {
80 let deployment_id = settings
81 .deployment_id
82 .clone()
83 .ok_or_else(|| anyhow!("no Azure OpenAI deployment ID"))?;
84 let api_version = settings
85 .api_version
86 .ok_or_else(|| anyhow!("no Azure OpenAI API version"))?;
87
88 Ok(OpenAiCompletionProviderKind::AzureOpenAi {
89 deployment_id,
90 api_version,
91 })
92 }
93 }
94 }
95
96 pub fn provider_api_url(&self) -> anyhow::Result<String> {
97 match &self.provider {
98 AiProviderSettings::OpenAi(settings) => Ok(settings
99 .api_url
100 .clone()
101 .unwrap_or_else(|| OPEN_AI_API_URL.to_string())),
102 AiProviderSettings::AzureOpenAi(settings) => settings
103 .api_url
104 .clone()
105 .ok_or_else(|| anyhow!("no Azure OpenAI API URL")),
106 }
107 }
108
109 pub fn provider_model(&self) -> anyhow::Result<OpenAiModel> {
110 match &self.provider {
111 AiProviderSettings::OpenAi(settings) => {
112 Ok(settings.default_model.unwrap_or(OpenAiModel::FourTurbo))
113 }
114 AiProviderSettings::AzureOpenAi(_settings) => {
115 // TODO: We need to use an Azure OpenAI model here.
116 Ok(OpenAiModel::FourTurbo)
117 }
118 }
119 }
120
121 pub fn provider_model_name(&self) -> anyhow::Result<String> {
122 match &self.provider {
123 AiProviderSettings::OpenAi(settings) => Ok(settings
124 .default_model
125 .unwrap_or(OpenAiModel::FourTurbo)
126 .full_name()
127 .to_string()),
128 AiProviderSettings::AzureOpenAi(settings) => settings
129 .deployment_id
130 .clone()
131 .ok_or_else(|| anyhow!("no Azure OpenAI deployment ID")),
132 }
133 }
134}
135
136impl Settings for AssistantSettings {
137 const KEY: Option<&'static str> = Some("assistant");
138
139 type FileContent = AssistantSettingsContent;
140
141 fn load(
142 default_value: &Self::FileContent,
143 user_values: &[&Self::FileContent],
144 _: &mut gpui::AppContext,
145 ) -> anyhow::Result<Self> {
146 Self::load_via_json_merge(default_value, user_values)
147 }
148}
149
150/// Assistant panel settings
151#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
152pub struct AssistantSettingsContent {
153 /// Whether to show the assistant panel button in the status bar.
154 ///
155 /// Default: true
156 pub button: Option<bool>,
157 /// Where to dock the assistant.
158 ///
159 /// Default: right
160 pub dock: Option<AssistantDockPosition>,
161 /// Default width in pixels when the assistant is docked to the left or right.
162 ///
163 /// Default: 640
164 pub default_width: Option<f32>,
165 /// Default height in pixels when the assistant is docked to the bottom.
166 ///
167 /// Default: 320
168 pub default_height: Option<f32>,
169 /// Deprecated: Please use `provider.default_model` instead.
170 /// The default OpenAI model to use when starting new conversations.
171 ///
172 /// Default: gpt-4-1106-preview
173 #[deprecated = "Please use `provider.default_model` instead."]
174 pub default_open_ai_model: Option<OpenAiModel>,
175 /// Deprecated: Please use `provider.api_url` instead.
176 /// OpenAI API base URL to use when starting new conversations.
177 ///
178 /// Default: https://api.openai.com/v1
179 #[deprecated = "Please use `provider.api_url` instead."]
180 pub openai_api_url: Option<String>,
181 /// The settings for the AI provider.
182 #[serde(default)]
183 pub provider: AiProviderSettingsContent,
184}
185
186#[derive(Debug, Clone, Deserialize)]
187#[serde(tag = "type", rename_all = "snake_case")]
188pub enum AiProviderSettings {
189 /// The settings for the OpenAI provider.
190 #[serde(rename = "openai")]
191 OpenAi(OpenAiProviderSettings),
192 /// The settings for the Azure OpenAI provider.
193 #[serde(rename = "azure_openai")]
194 AzureOpenAi(AzureOpenAiProviderSettings),
195}
196
197/// The settings for the AI provider used by the Zed Assistant.
198#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
199#[serde(tag = "type", rename_all = "snake_case")]
200pub enum AiProviderSettingsContent {
201 /// The settings for the OpenAI provider.
202 #[serde(rename = "openai")]
203 OpenAi(OpenAiProviderSettingsContent),
204 /// The settings for the Azure OpenAI provider.
205 #[serde(rename = "azure_openai")]
206 AzureOpenAi(AzureOpenAiProviderSettingsContent),
207}
208
209impl Default for AiProviderSettingsContent {
210 fn default() -> Self {
211 Self::OpenAi(OpenAiProviderSettingsContent::default())
212 }
213}
214
215#[derive(Debug, Clone, Deserialize)]
216pub struct OpenAiProviderSettings {
217 /// The OpenAI API base URL to use when starting new conversations.
218 pub api_url: Option<String>,
219 /// The default OpenAI model to use when starting new conversations.
220 pub default_model: Option<OpenAiModel>,
221}
222
223#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
224pub struct OpenAiProviderSettingsContent {
225 /// The OpenAI API base URL to use when starting new conversations.
226 ///
227 /// Default: https://api.openai.com/v1
228 pub api_url: Option<String>,
229 /// The default OpenAI model to use when starting new conversations.
230 ///
231 /// Default: gpt-4-1106-preview
232 pub default_model: Option<OpenAiModel>,
233}
234
235#[derive(Debug, Clone, Deserialize)]
236pub struct AzureOpenAiProviderSettings {
237 /// The Azure OpenAI API base URL to use when starting new conversations.
238 pub api_url: Option<String>,
239 /// The Azure OpenAI API version.
240 pub api_version: Option<AzureOpenAiApiVersion>,
241 /// The Azure OpenAI API deployment ID.
242 pub deployment_id: Option<String>,
243}
244
245#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
246pub struct AzureOpenAiProviderSettingsContent {
247 /// The Azure OpenAI API base URL to use when starting new conversations.
248 pub api_url: Option<String>,
249 /// The Azure OpenAI API version.
250 pub api_version: Option<AzureOpenAiApiVersion>,
251 /// The Azure OpenAI deployment ID.
252 pub deployment_id: Option<String>,
253}